aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/platform/ios7/README.md (renamed from backends/platform/iphone/README.md)0
-rw-r--r--backends/platform/ios7/iphone_common.h111
-rw-r--r--backends/platform/ios7/iphone_keyboard.h44
-rw-r--r--backends/platform/ios7/iphone_keyboard.mm98
-rw-r--r--backends/platform/ios7/iphone_main.mm154
-rw-r--r--backends/platform/ios7/iphone_video.h109
-rw-r--r--backends/platform/ios7/iphone_video.mm821
-rw-r--r--backends/platform/ios7/module.mk15
-rw-r--r--backends/platform/ios7/osys_events.cpp562
-rw-r--r--backends/platform/ios7/osys_main.cpp344
-rw-r--r--backends/platform/ios7/osys_main.h224
-rw-r--r--backends/platform/ios7/osys_sound.cpp105
-rw-r--r--backends/platform/ios7/osys_video.mm503
-rw-r--r--backends/platform/iphone/iphone_common.h8
-rw-r--r--backends/platform/iphone/iphone_keyboard.h5
-rw-r--r--backends/platform/iphone/iphone_keyboard.mm45
-rw-r--r--backends/platform/iphone/iphone_main.mm38
-rw-r--r--backends/platform/iphone/iphone_video.h4
-rw-r--r--backends/platform/iphone/iphone_video.mm362
-rw-r--r--backends/platform/iphone/osys_events.cpp211
-rw-r--r--backends/platform/iphone/osys_main.cpp27
-rw-r--r--backends/platform/iphone/osys_main.h5
-rwxr-xr-xconfigure36
-rw-r--r--devtools/create_project/xcode.cpp14
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/Contents.json)0
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29.png)bin3084 -> 3084 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png)bin6829 -> 6829 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png)bin12228 -> 12228 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40.png)bin4356 -> 4356 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png)bin10744 -> 10744 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png)bin18115 -> 18115 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png)bin18115 -> 18115 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png)bin33953 -> 33953 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76.png)bin10147 -> 10147 bytes
-rw-r--r--dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png (renamed from dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png)bin26351 -> 26351 bytes
-rw-r--r--dists/ios7/Images.xcassets/Contents.json (renamed from dists/iphone/Images.xcassets/Contents.json)0
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/Contents.json)0
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png)bin239614 -> 239614 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png)bin942974 -> 942974 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png)bin1069512 -> 1069512 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png)bin671669 -> 671669 bytes
-rw-r--r--dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png (renamed from dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png)bin185340 -> 185340 bytes
-rw-r--r--dists/ios7/Info.plist52
-rw-r--r--dists/ios7/Info.plist.in52
-rw-r--r--dists/iphone/Default.pngbin0 -> 32558 bytes
-rw-r--r--dists/iphone/Info.plist35
-rw-r--r--dists/iphone/Info.plist.in35
-rw-r--r--dists/iphone/icon-72.pngbin0 -> 9695 bytes
-rw-r--r--dists/iphone/icon.pngbin0 -> 4741 bytes
-rw-r--r--dists/iphone/icon4.pngbin0 -> 15849 bytes
-rw-r--r--ports.mk71
51 files changed, 3579 insertions, 511 deletions
diff --git a/backends/platform/iphone/README.md b/backends/platform/ios7/README.md
index 0e22e6d2bd..0e22e6d2bd 100644
--- a/backends/platform/iphone/README.md
+++ b/backends/platform/ios7/README.md
diff --git a/backends/platform/ios7/iphone_common.h b/backends/platform/ios7/iphone_common.h
new file mode 100644
index 0000000000..94836dabcd
--- /dev/null
+++ b/backends/platform/ios7/iphone_common.h
@@ -0,0 +1,111 @@
+/* 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"
+
+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
+};
+
+struct VideoContext {
+ VideoContext() : asprectRatioCorrection(), screenWidth(), screenHeight(), overlayVisible(false),
+ overlayWidth(), overlayHeight(), mouseX(), mouseY(),
+ mouseHotspotX(), mouseHotspotY(), mouseWidth(), mouseHeight(),
+ mouseIsVisible(), graphicsMode(kGraphicsModeLinear), 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
+void iPhone_updateScreen();
+bool iPhone_fetchEvent(InternalEvent *event);
+const char *iPhone_getDocumentsDir();
+bool iPhone_isHighResDevice();
+
+uint getSizeNextPOT(uint size);
+
+#endif
diff --git a/backends/platform/ios7/iphone_keyboard.h b/backends/platform/ios7/iphone_keyboard.h
new file mode 100644
index 0000000000..ddd8f436e5
--- /dev/null
+++ b/backends/platform/ios7/iphone_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/iphone_keyboard.mm b/backends/platform/ios7/iphone_keyboard.mm
new file mode 100644
index 0000000000..0588aac8ab
--- /dev/null
+++ b/backends/platform/ios7/iphone_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 "iphone_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/iphone_main.mm b/backends/platform/ios7/iphone_main.mm
new file mode 100644
index 0000000000..02d46c1995
--- /dev/null
+++ b/backends/platform/ios7/iphone_main.mm
@@ -0,0 +1,154 @@
+/* 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 "iphone_video.h"
+
+void iphone_main(int argc, char *argv[]);
+
+@interface ScummVMViewController : UIViewController
+
+@end
+
+@implementation ScummVMViewController
+
+- (BOOL)prefersStatusBarHidden {
+ return YES;
+}
+
+@end
+
+@interface iPhoneMain : UIApplication {
+ UIWindow *_window;
+ ScummVMViewController *_controller;
+ iPhoneView *_view;
+}
+
+- (void)mainLoop:(id)param;
+- (iPhoneView *)getView;
+- (UIWindow *)getWindow;
+- (void)didRotate:(NSNotification *)notification;
+@end
+
+static int g_argc;
+static char **g_argv;
+
+int main(int argc, char **argv) {
+ g_argc = argc;
+ g_argv = argv;
+
+ NSAutoreleasePool *autoreleasePool = [
+ [NSAutoreleasePool alloc] init
+ ];
+
+ int returnCode = UIApplicationMain(argc, argv, @"iPhoneMain", @"iPhoneMain");
+ [autoreleasePool release];
+ return returnCode;
+}
+
+@implementation iPhoneMain
+
+-(id) init {
+ [super init];
+ _window = nil;
+ _view = nil;
+ return self;
+}
+
+- (void)mainLoop:(id)param {
+ [[NSAutoreleasePool alloc] init];
+
+ iphone_main(g_argc, g_argv);
+ exit(0);
+}
+
+- (iPhoneView *)getView {
+ return _view;
+}
+
+- (void)applicationDidFinishLaunching:(UIApplication *)application {
+ CGRect rect = [[UIScreen mainScreen] bounds];
+
+ // Create the directory for savegames
+#ifdef IPHONE_OFFICIAL
+ NSFileManager *fm = [NSFileManager defaultManager];
+ NSString *documentPath = [NSString stringWithUTF8String:iPhone_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 = [[ScummVMViewController 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)applicationDidResume {
+}
+
+- (void)applicationWillSuspend {
+}
+
+- (void)applicationWillTerminate {
+}
+
+- (void)applicationSuspend:(struct __GSEvent *)event {
+ //[self setApplicationBadge:NSLocalizedString(@"ON", nil)];
+ [_view applicationSuspend];
+}
+
+- (void)applicationResume:(struct __GSEvent *)event {
+ [_view applicationResume];
+}
+
+- (void)didRotate:(NSNotification *)notification {
+ UIDeviceOrientation screenOrientation = [[UIDevice currentDevice] orientation];
+ [_view deviceOrientationChanged:screenOrientation];
+}
+
+- (UIWindow*) getWindow {
+ return _window;
+}
+
+@end
diff --git a/backends/platform/ios7/iphone_video.h b/backends/platform/ios7/iphone_video.h
new file mode 100644
index 0000000000..5c9766a116
--- /dev/null
+++ b/backends/platform/ios7/iphone_video.h
@@ -0,0 +1,109 @@
+/* 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/ES1/gl.h>
+#include <OpenGLES/ES1/glext.h>
+
+#include "iphone_keyboard.h"
+#include "iphone_common.h"
+
+#include "common/list.h"
+
+@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;
+
+ GLint _renderBufferWidth;
+ GLint _renderBufferHeight;
+
+ GLfloat _gameScreenVertCoords[4 * 2];
+ GLfloat _gameScreenTexCoords[4 * 2];
+ CGRect _gameScreenRect;
+
+ GLfloat _overlayVertCoords[4 * 2];
+ GLfloat _overlayTexCoords[4 * 2];
+ CGRect _overlayRect;
+
+ GLfloat _mouseVertCoords[4 * 2];
+ GLfloat _mouseTexCoords[4 * 2];
+ GLint _mouseHotspotX, _mouseHotspotY;
+ GLint _mouseWidth, _mouseHeight;
+ GLfloat _mouseScaleX, _mouseScaleY;
+
+ int _scaledShakeOffsetY;
+ CGFloat _contentScaleFactor;
+
+ UITouch *_firstTouch;
+ UITouch *_secondTouch;
+}
+
+- (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
+
+extern iPhoneView *g_iPhoneViewInstance;
+
+#endif
diff --git a/backends/platform/ios7/iphone_video.mm b/backends/platform/ios7/iphone_video.mm
new file mode 100644
index 0000000000..efd8ea3acf
--- /dev/null
+++ b/backends/platform/ios7/iphone_video.mm
@@ -0,0 +1,821 @@
+/* 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 "iphone_video.h"
+
+#include "graphics/colormasks.h"
+#include "common/system.h"
+
+iPhoneView *g_iPhoneViewInstance = nil;
+static int g_fullWidth;
+static int g_fullHeight;
+
+static int g_needsScreenUpdate = 0;
+
+#if 0
+static long g_lastTick = 0;
+static int g_frames = 0;
+#endif
+
+extern bool iphone_touchpadModeEnabled();
+
+#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 iPhone_isHighResDevice() {
+ return g_fullHeight > 480;
+}
+
+void iPhone_updateScreen() {
+ //printf("Mouse: (%i, %i)\n", mouseX, mouseY);
+ if (!g_needsScreenUpdate) {
+ g_needsScreenUpdate = 1;
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO];
+ }
+}
+
+bool iPhone_fetchEvent(InternalEvent *event) {
+ return [g_iPhoneViewInstance fetchEvent:event];
+}
+
+uint getSizeNextPOT(uint size) {
+ if ((size & (size - 1)) || !size) {
+ int log = 0;
+
+ while (size >>= 1)
+ ++log;
+
+ size = (2 << log);
+ }
+
+ return size;
+}
+
+const char *iPhone_getDocumentsDir() {
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+ return [documentsDirectory UTF8String];
+}
+
+@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:kEAGLRenderingAPIOpenGLES1];
+
+ // 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]) {
+ glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError();
+ glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError();
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError();
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+ [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
+
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+
+ // Retrieve the render buffer size. This *should* match the frame size,
+ // i.e. g_fullWidth and g_fullHeight.
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError();
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError();
+
+ if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+ NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ return;
+ }
+ uint maxValue = MAX(_renderBufferWidth, _renderBufferHeight), maxValuePOT = getSizeNextPOT(maxValue);
+ uint minValue = MIN(_renderBufferWidth, _renderBufferHeight), minValuePOT = getSizeNextPOT(minValue);
+
+ _videoContext.overlayWidth = maxValue;
+ _videoContext.overlayHeight = minValue;
+
+ uint overlayTextureWidth = maxValuePOT;
+ uint overlayTextureHeight = minValuePOT;
+
+ // 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.
+ _overlayTexCoords[2] = _overlayTexCoords[6] = _videoContext.overlayWidth / (GLfloat)overlayTextureWidth;
+ _overlayTexCoords[5] = _overlayTexCoords[7] = _videoContext.overlayHeight / (GLfloat)overlayTextureHeight;
+
+ _videoContext.overlayTexture.create(overlayTextureWidth, overlayTextureHeight, Graphics::createPixelFormat<5551>());
+
+ glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError();
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_TEXTURE_2D); printOpenGLError();
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError();
+ glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError();
+ }
+}
+
+- (void)setupGestureRecognizers {
+ UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeRight:)];
+ swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
+ swipeRight.numberOfTouchesRequired = 2;
+
+ UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeLeft:)];
+ swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
+ swipeLeft.numberOfTouchesRequired = 2;
+
+ UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeUp:)];
+ swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
+ swipeUp.numberOfTouchesRequired = 2;
+
+ UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeDown:)];
+ swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
+ swipeDown.numberOfTouchesRequired = 2;
+
+ UITapGestureRecognizer *doubleTapTwoFingers = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersDoubleTap:)];
+ doubleTapTwoFingers.numberOfTapsRequired = 2;
+ doubleTapTwoFingers.numberOfTouchesRequired = 2;
+
+ [self addGestureRecognizer:swipeRight];
+ [self addGestureRecognizer:swipeLeft];
+ [self addGestureRecognizer:swipeUp];
+ [self addGestureRecognizer:swipeDown];
+ [self addGestureRecognizer:doubleTapTwoFingers];
+}
+
+- (CGFloat)optimalScale {
+ CGFloat screenScale = [[UIScreen mainScreen] scale];
+ if (screenScale < 2) return screenScale;
+
+ if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
+ return 1;
+ }
+
+ CGSize screenSize;
+ UIScreen *mainScreen = [UIScreen mainScreen];
+ if ([mainScreen respondsToSelector:@selector(nativeBounds)]) {
+ screenSize = [mainScreen nativeBounds].size;
+ }
+ else {
+ screenSize = [mainScreen bounds].size;
+ screenSize.width *= screenScale;
+ screenSize.height *= screenScale;
+ }
+ CGFloat mxSize = MAX(screenSize.width, screenSize.height);
+
+ if (mxSize <= 1136) {
+ // iPhone 4S / 5 / 5S / 5C
+ return 1;
+ }
+ else {
+ // iPhone 6 / 6S / 6+ / 6S+
+ return 2;
+ }
+}
+
+- (id)initWithFrame:(struct CGRect)frame {
+ self = [super initWithFrame: frame];
+
+ [self setupGestureRecognizers];
+
+ g_fullWidth = (int)MAX(frame.size.width, frame.size.height);
+ g_fullHeight = (int)MIN(frame.size.width, frame.size.height);
+
+ _contentScaleFactor = [self optimalScale];
+ [self setContentScaleFactor:_contentScaleFactor];
+
+ g_iPhoneViewInstance = self;
+
+ _keyboardView = nil;
+ _screenTexture = 0;
+ _overlayTexture = 0;
+ _mouseCursorTexture = 0;
+
+ _scaledShakeOffsetY = 0;
+
+ _firstTouch = NULL;
+ _secondTouch = NULL;
+
+ _eventLock = [[NSLock alloc] init];
+
+ _gameScreenVertCoords[0] = _gameScreenVertCoords[1] =
+ _gameScreenVertCoords[2] = _gameScreenVertCoords[3] =
+ _gameScreenVertCoords[4] = _gameScreenVertCoords[5] =
+ _gameScreenVertCoords[6] = _gameScreenVertCoords[7] = 0;
+
+ _gameScreenTexCoords[0] = _gameScreenTexCoords[1] =
+ _gameScreenTexCoords[2] = _gameScreenTexCoords[3] =
+ _gameScreenTexCoords[4] = _gameScreenTexCoords[5] =
+ _gameScreenTexCoords[6] = _gameScreenTexCoords[7] = 0;
+
+ _overlayVertCoords[0] = _overlayVertCoords[1] =
+ _overlayVertCoords[2] = _overlayVertCoords[3] =
+ _overlayVertCoords[4] = _overlayVertCoords[5] =
+ _overlayVertCoords[6] = _overlayVertCoords[7] = 0;
+
+ _overlayTexCoords[0] = _overlayTexCoords[1] =
+ _overlayTexCoords[2] = _overlayTexCoords[3] =
+ _overlayTexCoords[4] = _overlayTexCoords[5] =
+ _overlayTexCoords[6] = _overlayTexCoords[7] = 0;
+
+ _mouseVertCoords[0] = _mouseVertCoords[1] =
+ _mouseVertCoords[2] = _mouseVertCoords[3] =
+ _mouseVertCoords[4] = _mouseVertCoords[5] =
+ _mouseVertCoords[6] = _mouseVertCoords[7] = 0;
+
+ _mouseTexCoords[0] = _mouseTexCoords[1] =
+ _mouseTexCoords[2] = _mouseTexCoords[3] =
+ _mouseTexCoords[4] = _mouseTexCoords[5] =
+ _mouseTexCoords[6] = _mouseTexCoords[7] = 0;
+
+ // Initialize the OpenGL ES context
+ [self createContext];
+
+ return self;
+}
+
+- (void)dealloc {
+ if (_keyboardView != nil) {
+ [_keyboardView dealloc];
+ }
+
+ _videoContext.screenTexture.free();
+ _videoContext.overlayTexture.free();
+ _videoContext.mouseTexture.free();
+
+ [_eventLock dealloc];
+ [super dealloc];
+}
+
+#if 0
+- (void)drawRect:(CGRect)frame {
+ if (g_lastTick == 0) {
+ g_lastTick = time(0);
+ }
+
+ g_frames++;
+ if (time(0) > g_lastTick) {
+ g_lastTick = time(0);
+ printf("FPS: %i\n", g_frames);
+ g_frames = 0;
+ }
+}
+#endif
+
+- (void)setFilterModeForTexture:(GLuint)tex {
+ if (!tex)
+ return;
+
+ glBindTexture(GL_TEXTURE_2D, tex); printOpenGLError();
+
+ GLint filter = GL_LINEAR;
+
+ switch (_videoContext.graphicsMode) {
+ case kGraphicsModeLinear:
+ filter = GL_LINEAR;
+ break;
+
+ case kGraphicsModeNone:
+ filter = GL_NEAREST;
+ 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();
+}
+
+- (void)setGraphicsMode {
+ [self setFilterModeForTexture:_screenTexture];
+ [self setFilterModeForTexture:_overlayTexture];
+ [self setFilterModeForTexture:_mouseCursorTexture];
+}
+
+- (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];
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+ [_context presentRenderbuffer:GL_RENDERBUFFER_OES];
+
+}
+
+- (void)notifyMouseMove {
+ const GLint mouseX = (GLint)(_videoContext.mouseX * _mouseScaleX) - _mouseHotspotX;
+ const GLint mouseY = (GLint)(_videoContext.mouseY * _mouseScaleY) - _mouseHotspotY;
+
+ _mouseVertCoords[0] = _mouseVertCoords[4] = mouseX;
+ _mouseVertCoords[1] = _mouseVertCoords[3] = mouseY;
+ _mouseVertCoords[2] = _mouseVertCoords[6] = mouseX + _mouseWidth;
+ _mouseVertCoords[5] = _mouseVertCoords[7] = 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 {
+ if (_mouseCursorTexture == 0) {
+ glGenTextures(1, &_mouseCursorTexture); printOpenGLError();
+ [self setFilterModeForTexture:_mouseCursorTexture];
+ }
+
+ [self updateMouseCursorScaling];
+
+ _mouseTexCoords[2] = _mouseTexCoords[6] = _videoContext.mouseWidth / (GLfloat)_videoContext.mouseTexture.w;
+ _mouseTexCoords[5] = _mouseTexCoords[7] = _videoContext.mouseHeight / (GLfloat)_videoContext.mouseTexture.h;
+
+ glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError();
+ 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 {
+ glVertexPointer(2, GL_FLOAT, 0, _gameScreenVertCoords); printOpenGLError();
+ glTexCoordPointer(2, GL_FLOAT, 0, _gameScreenTexCoords); printOpenGLError();
+
+ glBindTexture(GL_TEXTURE_2D, _screenTexture); printOpenGLError();
+
+ // 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.
+ 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();
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
+}
+
+- (void)updateOverlaySurface {
+ glVertexPointer(2, GL_FLOAT, 0, _overlayVertCoords); printOpenGLError();
+ glTexCoordPointer(2, GL_FLOAT, 0, _overlayTexCoords); printOpenGLError();
+
+ glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError();
+ 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 {
+ glVertexPointer(2, GL_FLOAT, 0, _mouseVertCoords); printOpenGLError();
+ glTexCoordPointer(2, GL_FLOAT, 0, _mouseTexCoords); printOpenGLError();
+
+ 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);
+
+ _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth;
+ _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight;
+
+ _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>());
+}
+
+- (void)initSurface {
+ if (_context) {
+ glDeleteTextures(1, &_screenTexture); printOpenGLError();
+ glDeleteTextures(1, &_overlayTexture); printOpenGLError();
+
+ glDeleteRenderbuffersOES(1, &_viewRenderbuffer);
+ glDeleteFramebuffersOES(1, &_viewFramebuffer);
+
+ glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError();
+ glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError();
+
+ glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError();
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+ [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
+
+ glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError();
+ glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError();
+
+ if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
+ NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
+ return;
+ }
+
+ glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError();
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError();
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ glEnable(GL_TEXTURE_2D); printOpenGLError();
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError();
+ glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError();
+ }
+
+ BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]);
+
+// glMatrixMode(GL_PROJECTION);
+// glLoadIdentity();
+
+ int screenWidth, screenHeight;
+ if (isLandscape) {
+ screenWidth = MAX(_renderBufferWidth, _renderBufferHeight);
+ screenHeight = MIN(_renderBufferWidth, _renderBufferHeight);
+// glOrthof(0, screenWidth, screenHeight, 0, 0, 1); printOpenGLError();
+ }
+ else {
+ screenWidth = MIN(_renderBufferWidth, _renderBufferHeight);
+ screenHeight = MAX(_renderBufferWidth, _renderBufferHeight);
+// glOrthof(0, screenHeight, screenWidth, 0, 0, 1); printOpenGLError();
+ }
+
+ glGenTextures(1, &_screenTexture); printOpenGLError();
+ [self setFilterModeForTexture:_screenTexture];
+
+ glGenTextures(1, &_overlayTexture); printOpenGLError();
+ [self setFilterModeForTexture:_overlayTexture];
+
+ glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+
+ [self clearColorBuffer];
+
+// if (_keyboardView != nil) {
+// [_keyboardView removeFromSuperview];
+// [[_keyboardView inputView] removeFromSuperview];
+// }
+
+ 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);
+
+ _gameScreenVertCoords[0] = _gameScreenVertCoords[4] = CGRectGetMinX(_gameScreenRect);
+ _gameScreenVertCoords[1] = _gameScreenVertCoords[3] = CGRectGetMinY(_gameScreenRect);
+ _gameScreenVertCoords[2] = _gameScreenVertCoords[6] = CGRectGetMaxX(_gameScreenRect);
+ _gameScreenVertCoords[5] = _gameScreenVertCoords[7] = CGRectGetMaxY(_gameScreenRect);
+
+ _overlayVertCoords[2] = _overlayVertCoords[6] = CGRectGetMaxX(_overlayRect);
+ _overlayVertCoords[5] = _overlayVertCoords[7] = CGRectGetMaxY(_overlayRect);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrthof(0, screenWidth, screenHeight, 0, 0, 1);
+
+ [self setViewTransformation];
+ [self updateMouseCursorScaling];
+}
+
+- (void)setViewTransformation {
+ // Set the modelview matrix. This matrix will be used for the shake offset
+ // support.
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ // 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));
+
+ // Apply the shakeing to the output screen.
+ glTranslatef(0, -_scaledShakeOffsetY, 0);
+}
+
+- (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_OES];
+ }
+}
+
+- (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
+ // cooridnates.
+ point.x *= _contentScaleFactor;
+ point.y *= _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 (!iphone_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<UITouch *> *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<UITouch *> *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<UITouch *> *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..87721cc9e5
--- /dev/null
+++ b/backends/platform/ios7/module.mk
@@ -0,0 +1,15 @@
+MODULE := backends/platform/ios7
+
+MODULE_OBJS := \
+ osys_main.o \
+ osys_events.o \
+ osys_sound.o \
+ osys_video.o \
+ iphone_main.o \
+ iphone_video.o \
+ iphone_keyboard.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/ios7/osys_events.cpp b/backends/platform/ios7/osys_events.cpp
new file mode 100644
index 0000000000..19da580c80
--- /dev/null
+++ b/backends/platform/ios7/osys_events.cpp
@@ -0,0 +1,562 @@
+/* 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 "osys_main.h"
+
+static const int kQueuedInputEventDelay = 50;
+
+bool OSystem_IPHONE::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 (iPhone_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;
+ break;
+
+ case kInputApplicationSuspended:
+ suspendLoop();
+ return false;
+ break;
+
+ 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_IPHONE::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_IPHONE::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_IPHONE::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_IPHONE::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_IPHONE::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_IPHONE::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_IPHONE::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;
+ updateOutputSurface();
+
+ dirtyFullScreen();
+ if (_videoContext->overlayVisible)
+ dirtyFullOverlayScreen();
+ updateScreen();
+ }
+}
+
+void OSystem_IPHONE::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_IPHONE::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_IPHONE::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/osys_main.cpp b/backends/platform/ios7/osys_main.cpp
new file mode 100644
index 0000000000..ef3499d597
--- /dev/null
+++ b/backends/platform/ios7/osys_main.cpp
@@ -0,0 +1,344 @@
+/* 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 <sys/time.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 "osys_main.h"
+
+
+const OSystem::GraphicsMode OSystem_IPHONE::s_supportedGraphicsModes[] = {
+ { "linear", "Linear filtering", kGraphicsModeLinear },
+ { "none", "No filtering", kGraphicsModeNone },
+ { 0, 0, 0 }
+};
+
+AQCallbackStruct OSystem_IPHONE::s_AudioQueue;
+SoundProc OSystem_IPHONE::s_soundCallback = NULL;
+void *OSystem_IPHONE::s_soundParam = NULL;
+
+OSystem_IPHONE::OSystem_IPHONE() :
+ _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),
+ _mouseCursorPaletteEnabled(false), _gfxTransactionError(kTransactionSuccess) {
+ _queuedInputEvent.type = Common::EVENT_INVALID;
+ _touchpadModeEnabled = !iPhone_isHighResDevice();
+#ifdef IPHONE_OFFICIAL
+ _fsFactory = new ChRootFilesystemFactory(iPhone_getDocumentsDir());
+#else
+ _fsFactory = new POSIXFilesystemFactory();
+#endif
+ initVideoContext();
+
+ memset(_gamePalette, 0, sizeof(_gamePalette));
+ memset(_gamePaletteRGBA5551, 0, sizeof(_gamePaletteRGBA5551));
+ memset(_mouseCursorPalette, 0, sizeof(_mouseCursorPalette));
+}
+
+OSystem_IPHONE::~OSystem_IPHONE() {
+ 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_IPHONE::touchpadModeEnabled() const {
+ return _touchpadModeEnabled;
+}
+
+int OSystem_IPHONE::timerHandler(int t) {
+ DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
+ tm->handler();
+ return t;
+}
+
+void OSystem_IPHONE::initBackend() {
+#ifdef IPHONE_OFFICIAL
+ _savefileManager = new DefaultSaveFileManager("/Savegames");
+#else
+ _savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
+#endif
+
+ _timerManager = new DefaultTimerManager();
+
+ gettimeofday(&_startTime, NULL);
+
+ setupMixer();
+
+ setTimerCallback(&OSystem_IPHONE::timerHandler, 10);
+
+ EventsBaseBackend::initBackend();
+}
+
+bool OSystem_IPHONE::hasFeature(Feature f) {
+ switch (f) {
+ case kFeatureCursorPalette:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+void OSystem_IPHONE::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_IPHONE::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureCursorPalette:
+ return _mouseCursorPaletteEnabled;
+ case kFeatureAspectRatioCorrection:
+ return _videoContext->asprectRatioCorrection;
+
+ default:
+ return false;
+ }
+}
+
+void OSystem_IPHONE::suspendLoop() {
+ bool done = false;
+ uint32 startTime = getMillis();
+
+ stopSoundsystem();
+
+ InternalEvent event;
+ while (!done) {
+ if (iPhone_fetchEvent(&event))
+ if (event.type == kInputApplicationResumed)
+ done = true;
+ usleep(100000);
+ }
+
+ startSoundsystem();
+
+ _timeSuspended += getMillis() - startTime;
+}
+
+uint32 OSystem_IPHONE::getMillis(bool skipRecord) {
+ //printf("getMillis()\n");
+
+ struct timeval currentTime;
+ gettimeofday(&currentTime, NULL);
+ return (uint32)(((currentTime.tv_sec - _startTime.tv_sec) * 1000) +
+ ((currentTime.tv_usec - _startTime.tv_usec) / 1000)) - _timeSuspended;
+}
+
+void OSystem_IPHONE::delayMillis(uint msecs) {
+ //printf("delayMillis(%d)\n", msecs);
+ usleep(msecs * 1000);
+}
+
+OSystem::MutexRef OSystem_IPHONE::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_IPHONE::lockMutex(MutexRef mutex) {
+ if (pthread_mutex_lock((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_lock() failed!\n");
+ }
+}
+
+void OSystem_IPHONE::unlockMutex(MutexRef mutex) {
+ if (pthread_mutex_unlock((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_unlock() failed!\n");
+ }
+}
+
+void OSystem_IPHONE::deleteMutex(MutexRef mutex) {
+ if (pthread_mutex_destroy((pthread_mutex_t *) mutex) != 0) {
+ printf("pthread_mutex_destroy() failed!\n");
+ } else {
+ free(mutex);
+ }
+}
+
+
+void OSystem_IPHONE::setTimerCallback(TimerProc callback, int interval) {
+ //printf("setTimerCallback()\n");
+
+ if (callback != NULL) {
+ _timerCallbackTimer = interval;
+ _timerCallbackNext = getMillis() + interval;
+ _timerCallback = callback;
+ } else
+ _timerCallback = NULL;
+}
+
+void OSystem_IPHONE::quit() {
+}
+
+void OSystem_IPHONE::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_IPHONE::getMixer() {
+ assert(_mixer);
+ return _mixer;
+}
+
+OSystem *OSystem_IPHONE_create() {
+ return new OSystem_IPHONE();
+}
+
+Common::String OSystem_IPHONE::getDefaultConfigFileName() {
+#ifdef IPHONE_OFFICIAL
+ Common::String path = "/Preferences";
+ return path;
+#else
+ return SCUMMVM_PREFS_PATH;
+#endif
+}
+
+void OSystem_IPHONE::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_OFFICIAL
+ POSIXFilesystemNode *posixNode = new POSIXFilesystemNode(bundlePath);
+ Common::FSNode *node = new Common::FSNode(posixNode);
+ s.add("__OSX_BUNDLE__", new Common::FSDirectory(*node), priority);
+#else
+ // OS X
+ s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority);
+#endif
+ }
+ CFRelease(fileUrl);
+ }
+}
+
+void OSystem_IPHONE::logMessage(LogMessageType::Type type, const char *message) {
+ FILE *output = 0;
+
+ if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
+ output = stdout;
+ else
+ output = stderr;
+
+ fputs(message, output);
+ fflush(output);
+}
+
+bool iphone_touchpadModeEnabled() {
+ OSystem_IPHONE *sys = (OSystem_IPHONE *) g_system;
+ return sys && sys->touchpadModeEnabled();
+}
+
+void iphone_main(int argc, char *argv[]) {
+
+ //OSystem_IPHONE::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_OFFICIAL
+ chdir(iPhone_getDocumentsDir());
+#else
+ system("mkdir " SCUMMVM_ROOT_PATH);
+ system("mkdir " SCUMMVM_SAVE_PATH);
+
+ chdir("/var/mobile/");
+#endif
+
+ g_system = OSystem_IPHONE_create();
+ assert(g_system);
+
+ // Invoke the actual ScummVM main entry point:
+ scummvm_main(argc, argv);
+ g_system->quit(); // TODO: Consider removing / replacing this!
+}
diff --git a/backends/platform/ios7/osys_main.h b/backends/platform/ios7/osys_main.h
new file mode 100644
index 0000000000..04a531613f
--- /dev/null
+++ b/backends/platform/ios7/osys_main.h
@@ -0,0 +1,224 @@
+/* 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 "iphone_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_IPHONE : 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;
+
+public:
+
+ OSystem_IPHONE();
+ virtual ~OSystem_IPHONE();
+
+ 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);
+
+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);
+
+ 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);
+};
+
+#endif
diff --git a/backends/platform/ios7/osys_sound.cpp b/backends/platform/ios7/osys_sound.cpp
new file mode 100644
index 0000000000..bfee06c6f2
--- /dev/null
+++ b/backends/platform/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 "osys_main.h"
+
+void OSystem_IPHONE::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_IPHONE::mixCallback(void *sys, byte *samples, int len) {
+ OSystem_IPHONE *this_ = (OSystem_IPHONE *)sys;
+ assert(this_);
+
+ if (this_->_mixer) {
+ this_->_mixer->mixCallback(samples, len);
+ }
+}
+
+void OSystem_IPHONE::setupMixer() {
+ _mixer = new Audio::MixerImpl(this, AUDIO_SAMPLE_RATE);
+
+ s_soundCallback = mixCallback;
+ s_soundParam = this;
+
+ startSoundsystem();
+}
+
+void OSystem_IPHONE::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_IPHONE::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/osys_video.mm b/backends/platform/ios7/osys_video.mm
new file mode 100644
index 0000000000..c76f432dda
--- /dev/null
+++ b/backends/platform/ios7/osys_video.mm
@@ -0,0 +1,503 @@
+/* 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 "osys_main.h"
+#include "iphone_video.h"
+
+#include "graphics/conversion.h"
+
+void OSystem_IPHONE::initVideoContext() {
+ _videoContext = [g_iPhoneViewInstance getVideoContext];
+}
+
+const OSystem::GraphicsMode *OSystem_IPHONE::getSupportedGraphicsModes() const {
+ return s_supportedGraphicsModes;
+}
+
+int OSystem_IPHONE::getDefaultGraphicsMode() const {
+ return kGraphicsModeLinear;
+}
+
+bool OSystem_IPHONE::setGraphicsMode(int mode) {
+ switch (mode) {
+ case kGraphicsModeNone:
+ case kGraphicsModeLinear:
+ _videoContext->graphicsMode = (GraphicsModes)mode;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+int OSystem_IPHONE::getGraphicsMode() const {
+ return _videoContext->graphicsMode;
+}
+
+#ifdef USE_RGB_COLOR
+Common::List<Graphics::PixelFormat> OSystem_IPHONE::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_IPHONE::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.
+ [g_iPhoneViewInstance 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_IPHONE::beginGFXTransaction() {
+ _gfxTransactionError = kTransactionSuccess;
+}
+
+OSystem::TransactionError OSystem_IPHONE::endGFXTransaction() {
+ _screenChangeCount++;
+ updateOutputSurface();
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(setGraphicsMode) withObject:nil waitUntilDone: YES];
+
+ return _gfxTransactionError;
+}
+
+void OSystem_IPHONE::updateOutputSurface() {
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES];
+}
+
+int16 OSystem_IPHONE::getHeight() {
+ return _videoContext->screenHeight;
+}
+
+int16 OSystem_IPHONE::getWidth() {
+ return _videoContext->screenWidth;
+}
+
+void OSystem_IPHONE::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_IPHONE::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_IPHONE::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_IPHONE::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;
+
+ iPhone_updateScreen();
+}
+
+void OSystem_IPHONE::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_IPHONE::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_IPHONE::lockScreen() {
+ //printf("lockScreen()\n");
+ return &_framebuffer;
+}
+
+void OSystem_IPHONE::unlockScreen() {
+ //printf("unlockScreen()\n");
+ dirtyFullScreen();
+}
+
+void OSystem_IPHONE::setShakePos(int shakeOffset) {
+ //printf("setShakePos(%i)\n", shakeOffset);
+ _videoContext->shakeOffsetY = shakeOffset;
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(setViewTransformation) withObject:nil waitUntilDone: YES];
+ // HACK: We use this to force a redraw.
+ _mouseDirty = true;
+}
+
+void OSystem_IPHONE::showOverlay() {
+ //printf("showOverlay()\n");
+ _videoContext->overlayVisible = true;
+ dirtyFullOverlayScreen();
+ updateScreen();
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES];
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES];
+}
+
+void OSystem_IPHONE::hideOverlay() {
+ //printf("hideOverlay()\n");
+ _videoContext->overlayVisible = false;
+ _dirtyOverlayRects.clear();
+ dirtyFullScreen();
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateMouseCursorScaling) withObject:nil waitUntilDone: YES];
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES];
+}
+
+void OSystem_IPHONE::clearOverlay() {
+ //printf("clearOverlay()\n");
+ bzero(_videoContext->overlayTexture.getPixels(), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch);
+ dirtyFullOverlayScreen();
+}
+
+void OSystem_IPHONE::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_IPHONE::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_IPHONE::getOverlayHeight() {
+ return _videoContext->overlayHeight;
+}
+
+int16 OSystem_IPHONE::getOverlayWidth() {
+ return _videoContext->overlayWidth;
+}
+
+bool OSystem_IPHONE::showMouse(bool visible) {
+ //printf("showMouse(%d)\n", visible);
+ bool last = _videoContext->mouseIsVisible;
+ _videoContext->mouseIsVisible = visible;
+ _mouseDirty = true;
+
+ return last;
+}
+
+void OSystem_IPHONE::warpMouse(int x, int y) {
+ //printf("warpMouse(%d, %d)\n", x, y);
+ _videoContext->mouseX = x;
+ _videoContext->mouseY = y;
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(notifyMouseMove) withObject:nil waitUntilDone: YES];
+ _mouseDirty = true;
+}
+
+void OSystem_IPHONE::dirtyFullScreen() {
+ if (!_fullScreenIsDirty) {
+ _dirtyRects.clear();
+ _dirtyRects.push_back(Common::Rect(0, 0, _videoContext->screenWidth, _videoContext->screenHeight));
+ _fullScreenIsDirty = true;
+ }
+}
+
+void OSystem_IPHONE::dirtyFullOverlayScreen() {
+ if (!_fullScreenOverlayIsDirty) {
+ _dirtyOverlayRects.clear();
+ _dirtyOverlayRects.push_back(Common::Rect(0, 0, _videoContext->overlayWidth, _videoContext->overlayHeight));
+ _fullScreenOverlayIsDirty = true;
+ }
+}
+
+void OSystem_IPHONE::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_IPHONE::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_IPHONE::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);
+ }
+ }
+
+ [g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES];
+}
diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h
index 94836dabcd..59dca84b85 100644
--- a/backends/platform/iphone/iphone_common.h
+++ b/backends/platform/iphone/iphone_common.h
@@ -36,8 +36,7 @@ enum InputEvent {
kInputKeyPressed,
kInputApplicationSuspended,
kInputApplicationResumed,
- kInputSwipe,
- kInputTap
+ kInputSwipe
};
enum ScreenOrientation {
@@ -53,11 +52,6 @@ enum UIViewSwipeDirection {
kUIViewSwipeRight = 8
};
-enum UIViewTapDescription {
- kUIViewTapSingle = 1,
- kUIViewTapDouble = 2
-};
-
enum GraphicsModes {
kGraphicsModeLinear = 0,
kGraphicsModeNone = 1
diff --git a/backends/platform/iphone/iphone_keyboard.h b/backends/platform/iphone/iphone_keyboard.h
index ddd8f436e5..d54df9ac96 100644
--- a/backends/platform/iphone/iphone_keyboard.h
+++ b/backends/platform/iphone/iphone_keyboard.h
@@ -26,7 +26,7 @@
#include <UIKit/UIKit.h>
#include <UIKit/UITextView.h>
-@interface SoftKeyboard : UIView<UITextViewDelegate> {
+@interface SoftKeyboard : UIView {
id inputDelegate;
UITextView *inputView;
}
@@ -36,9 +36,6 @@
- (void)setInputDelegate:(id)delegate;
- (void)handleKeyPress:(unichar)c;
-- (void)showKeyboard;
-- (void)hideKeyboard;
-
@end
#endif
diff --git a/backends/platform/iphone/iphone_keyboard.mm b/backends/platform/iphone/iphone_keyboard.mm
index 0588aac8ab..39d68aff81 100644
--- a/backends/platform/iphone/iphone_keyboard.mm
+++ b/backends/platform/iphone/iphone_keyboard.mm
@@ -43,13 +43,31 @@
self = [super initWithFrame:CGRectMake(0.0f, 0.0f, 0.0f, 0.0f)];
softKeyboard = keyboard;
- [self setAutocorrectionType:UITextAutocorrectionTypeNo];
- [self setAutocapitalizationType:UITextAutocapitalizationTypeNone];
- [self setEnablesReturnKeyAutomatically:NO];
+ [[self textInputTraits] setAutocorrectionType:(UITextAutocorrectionType)1];
+ [[self textInputTraits] setAutocapitalizationType:(UITextAutocapitalizationType)0];
+ [[self textInputTraits] setEnablesReturnKeyAutomatically:NO];
return self;
}
+- (void) keyboardInputShouldDelete:(id)input {
+ [softKeyboard handleKeyPress:0x08];
+}
+
+- (BOOL)webView:(id)fp8 shouldInsertText:(id)character
+ replacingDOMRange:(id)fp16
+ givenAction:(int)fp20 {
+
+ if ([character length] != 1) {
+ [NSException raise:@"Unsupported" format:@"Unhandled multi-char insert!"];
+ return NO;
+ }
+
+ [softKeyboard handleKeyPress:[character characterAtIndex:0]];
+
+ return NO;
+}
+
@end
@@ -59,22 +77,9 @@
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;
}
@@ -87,12 +92,4 @@
[inputDelegate handleKeyPress:c];
}
-- (void)showKeyboard {
- [inputView becomeFirstResponder];
-}
-
-- (void)hideKeyboard {
- [inputView endEditing:YES];
-}
-
@end
diff --git a/backends/platform/iphone/iphone_main.mm b/backends/platform/iphone/iphone_main.mm
index 02d46c1995..3707f10a29 100644
--- a/backends/platform/iphone/iphone_main.mm
+++ b/backends/platform/iphone/iphone_main.mm
@@ -30,21 +30,8 @@
void iphone_main(int argc, char *argv[]);
-@interface ScummVMViewController : UIViewController
-
-@end
-
-@implementation ScummVMViewController
-
-- (BOOL)prefersStatusBarHidden {
- return YES;
-}
-
-@end
-
@interface iPhoneMain : UIApplication {
UIWindow *_window;
- ScummVMViewController *_controller;
iPhoneView *_view;
}
@@ -93,26 +80,19 @@ int main(int argc, char **argv) {
- (void)applicationDidFinishLaunching:(UIApplication *)application {
CGRect rect = [[UIScreen mainScreen] bounds];
- // Create the directory for savegames
-#ifdef IPHONE_OFFICIAL
- NSFileManager *fm = [NSFileManager defaultManager];
- NSString *documentPath = [NSString stringWithUTF8String:iPhone_getDocumentsDir()];
- NSString *savePath = [documentPath stringByAppendingPathComponent:@"Savegames"];
- if (![fm fileExistsAtPath:savePath]) {
- [fm createDirectoryAtPath:savePath withIntermediateDirectories:YES attributes:nil error:nil];
- }
-#endif
+ // hide the status bar
+ [application setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
+ [application setStatusBarHidden:YES animated:YES];
_window = [[UIWindow alloc] initWithFrame:rect];
[_window retain];
- _controller = [[ScummVMViewController alloc] init];
-
_view = [[iPhoneView alloc] initWithFrame:rect];
_view.multipleTouchEnabled = YES;
- _controller.view = _view;
- [_window setRootViewController:_controller];
+ [_window setContentView:_view];
+
+ [_window addSubview:_view];
[_window makeKeyAndVisible];
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
@@ -140,6 +120,12 @@ int main(int argc, char **argv) {
- (void)applicationResume:(struct __GSEvent *)event {
[_view applicationResume];
+
+ // Workaround, need to "hide" and unhide the statusbar to properly remove it,
+ // since the Springboard has put it back without apparently flagging our application.
+ [self setStatusBarHidden:YES animated:YES];
+ [self setStatusBarStyle:UIStatusBarStyleBlackTranslucent animated:NO];
+ [self setStatusBarHidden:YES animated:YES];
}
- (void)didRotate:(NSNotification *)notification {
diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h
index 5c9766a116..7dbf3c57ab 100644
--- a/backends/platform/iphone/iphone_video.h
+++ b/backends/platform/iphone/iphone_video.h
@@ -50,6 +50,8 @@
GLuint _overlayTexture;
GLuint _mouseCursorTexture;
+ UIDeviceOrientation _orientation;
+
GLint _renderBufferWidth;
GLint _renderBufferHeight;
@@ -78,6 +80,8 @@
- (VideoContext *)getVideoContext;
+- (void)drawRect:(CGRect)frame;
+
- (void)createScreenTexture;
- (void)initSurface;
- (void)setViewTransformation;
diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm
index efd8ea3acf..5048b57328 100644
--- a/backends/platform/iphone/iphone_video.mm
+++ b/backends/platform/iphone/iphone_video.mm
@@ -26,7 +26,6 @@
#include "iphone_video.h"
#include "graphics/colormasks.h"
-#include "common/system.h"
iPhoneView *g_iPhoneViewInstance = nil;
static int g_fullWidth;
@@ -39,8 +38,6 @@ static long g_lastTick = 0;
static int g_frames = 0;
#endif
-extern bool iphone_touchpadModeEnabled();
-
#define printOpenGLError() printOglError(__FILE__, __LINE__)
int printOglError(const char *file, int line) {
@@ -105,10 +102,8 @@ const char *iPhone_getDocumentsDir() {
CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer;
eaglLayer.opaque = YES;
- eaglLayer.drawableProperties = @{
- kEAGLDrawablePropertyRetainedBacking: @NO,
- kEAGLDrawablePropertyColorFormat: kEAGLColorFormatRGB565
- };
+ eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
+ [NSNumber numberWithBool:FALSE], kEAGLDrawablePropertyRetainedBacking, kEAGLColorFormatRGB565, kEAGLDrawablePropertyColorFormat, nil];
_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];
@@ -137,14 +132,11 @@ const char *iPhone_getDocumentsDir() {
NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
return;
}
- uint maxValue = MAX(_renderBufferWidth, _renderBufferHeight), maxValuePOT = getSizeNextPOT(maxValue);
- uint minValue = MIN(_renderBufferWidth, _renderBufferHeight), minValuePOT = getSizeNextPOT(minValue);
-
- _videoContext.overlayWidth = maxValue;
- _videoContext.overlayHeight = minValue;
- uint overlayTextureWidth = maxValuePOT;
- uint overlayTextureHeight = minValuePOT;
+ _videoContext.overlayHeight = _renderBufferWidth;
+ _videoContext.overlayWidth = _renderBufferHeight;
+ uint overlayTextureWidth = getSizeNextPOT(_videoContext.overlayHeight);
+ uint overlayTextureHeight = getSizeNextPOT(_videoContext.overlayWidth);
// Since the overlay size won't change the whole run, we can
// precalculate the texture coordinates for the overlay texture here
@@ -166,74 +158,31 @@ const char *iPhone_getDocumentsDir() {
}
}
-- (void)setupGestureRecognizers {
- UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeRight:)];
- swipeRight.direction = UISwipeGestureRecognizerDirectionRight;
- swipeRight.numberOfTouchesRequired = 2;
-
- UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeLeft:)];
- swipeLeft.direction = UISwipeGestureRecognizerDirectionLeft;
- swipeLeft.numberOfTouchesRequired = 2;
-
- UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeUp:)];
- swipeUp.direction = UISwipeGestureRecognizerDirectionUp;
- swipeUp.numberOfTouchesRequired = 2;
-
- UISwipeGestureRecognizer *swipeDown = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersSwipeDown:)];
- swipeDown.direction = UISwipeGestureRecognizerDirectionDown;
- swipeDown.numberOfTouchesRequired = 2;
-
- UITapGestureRecognizer *doubleTapTwoFingers = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(twoFingersDoubleTap:)];
- doubleTapTwoFingers.numberOfTapsRequired = 2;
- doubleTapTwoFingers.numberOfTouchesRequired = 2;
-
- [self addGestureRecognizer:swipeRight];
- [self addGestureRecognizer:swipeLeft];
- [self addGestureRecognizer:swipeUp];
- [self addGestureRecognizer:swipeDown];
- [self addGestureRecognizer:doubleTapTwoFingers];
-}
-
-- (CGFloat)optimalScale {
- CGFloat screenScale = [[UIScreen mainScreen] scale];
- if (screenScale < 2) return screenScale;
-
- if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
- return 1;
- }
-
- CGSize screenSize;
- UIScreen *mainScreen = [UIScreen mainScreen];
- if ([mainScreen respondsToSelector:@selector(nativeBounds)]) {
- screenSize = [mainScreen nativeBounds].size;
- }
- else {
- screenSize = [mainScreen bounds].size;
- screenSize.width *= screenScale;
- screenSize.height *= screenScale;
- }
- CGFloat mxSize = MAX(screenSize.width, screenSize.height);
-
- if (mxSize <= 1136) {
- // iPhone 4S / 5 / 5S / 5C
- return 1;
- }
- else {
- // iPhone 6 / 6S / 6+ / 6S+
- return 2;
- }
-}
-
- (id)initWithFrame:(struct CGRect)frame {
self = [super initWithFrame: frame];
- [self setupGestureRecognizers];
-
- g_fullWidth = (int)MAX(frame.size.width, frame.size.height);
- g_fullHeight = (int)MIN(frame.size.width, frame.size.height);
+ _contentScaleFactor = 1;
+ if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
+ if ([self respondsToSelector:@selector(setContentScaleFactor:)]) {
+ // Horrible and crazy method to get the proper return value of
+ // scale when the SDK used for building does not know anything
+ // about the selector scale...
+ NSMethodSignature *scaleSignature = [UIScreen instanceMethodSignatureForSelector:@selector(scale)];
+ NSInvocation *scaleInvocation = [NSInvocation invocationWithMethodSignature:scaleSignature];
+ [scaleInvocation setTarget:[UIScreen mainScreen]];
+ [scaleInvocation setSelector:@selector(scale)];
+ [scaleInvocation invoke];
+
+ NSInteger returnLength = [[scaleInvocation methodSignature] methodReturnLength];
+ if (returnLength == sizeof(CGFloat)) {
+ [scaleInvocation getReturnValue:&_contentScaleFactor];
+ [self setContentScaleFactor:_contentScaleFactor];
+ }
+ }
+ }
- _contentScaleFactor = [self optimalScale];
- [self setContentScaleFactor:_contentScaleFactor];
+ g_fullWidth = (int)frame.size.width;
+ g_fullHeight = (int)frame.size.height;
g_iPhoneViewInstance = self;
@@ -298,8 +247,8 @@ const char *iPhone_getDocumentsDir() {
[super dealloc];
}
-#if 0
- (void)drawRect:(CGRect)frame {
+#if 0
if (g_lastTick == 0) {
g_lastTick = time(0);
}
@@ -310,8 +259,8 @@ const char *iPhone_getDocumentsDir() {
printf("FPS: %i\n", g_frames);
g_frames = 0;
}
-}
#endif
+}
- (void)setFilterModeForTexture:(GLuint)tex {
if (!tex)
@@ -463,72 +412,69 @@ const char *iPhone_getDocumentsDir() {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
}
-- (void)createScreenTexture {
- const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth);
- const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight);
-
- _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth;
- _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight;
-
- _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>());
-}
-
-- (void)initSurface {
- if (_context) {
- glDeleteTextures(1, &_screenTexture); printOpenGLError();
- glDeleteTextures(1, &_overlayTexture); printOpenGLError();
+- (void)setUpOrientation:(UIDeviceOrientation)orientation width:(int *)width height:(int *)height {
+ _orientation = orientation;
- glDeleteRenderbuffersOES(1, &_viewRenderbuffer);
- glDeleteFramebuffersOES(1, &_viewFramebuffer);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
- glGenFramebuffersOES(1, &_viewFramebuffer); printOpenGLError();
- glGenRenderbuffersOES(1, &_viewRenderbuffer); printOpenGLError();
+ // We always force the origin (0,0) to be in the upper left corner.
+ switch (_orientation) {
+ case UIDeviceOrientationLandscapeRight:
+ glRotatef( 90, 0, 0, 1); printOpenGLError();
+ glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError();
- glBindFramebufferOES(GL_FRAMEBUFFER_OES, _viewFramebuffer); printOpenGLError();
- glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
- [_context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:(id<EAGLDrawable>)self.layer];
+ *width = _renderBufferHeight;
+ *height = _renderBufferWidth;
+ break;
- glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError();
+ case UIDeviceOrientationLandscapeLeft:
+ glRotatef(-90, 0, 0, 1); printOpenGLError();
+ glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError();
- glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &_renderBufferWidth); printOpenGLError();
- glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &_renderBufferHeight); printOpenGLError();
-
- if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES) {
- NSLog(@"Failed to make complete framebuffer object %x.", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
- return;
- }
+ *width = _renderBufferHeight;
+ *height = _renderBufferWidth;
+ break;
- glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError();
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError();
+ case UIDeviceOrientationPortrait:
+ default:
+ // We must force the portrait orientation here, since we might not know
+ // the real orientation.
+ _orientation = UIDeviceOrientationPortrait;
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glOrthof(0, _renderBufferWidth, _renderBufferHeight, 0, 0, 1); printOpenGLError();
- glEnable(GL_TEXTURE_2D); printOpenGLError();
- glEnableClientState(GL_TEXTURE_COORD_ARRAY); printOpenGLError();
- glEnableClientState(GL_VERTEX_ARRAY); printOpenGLError();
+ *width = _renderBufferWidth;
+ *height = _renderBufferHeight;
+ break;
}
+}
+
+- (void)createScreenTexture {
+ const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth);
+ const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight);
- BOOL isLandscape = (self.bounds.size.width > self.bounds.size.height); // UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]);
+ _gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth;
+ _gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight;
-// glMatrixMode(GL_PROJECTION);
-// glLoadIdentity();
+ _videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>());
+}
+- (void)initSurface {
int screenWidth, screenHeight;
- if (isLandscape) {
- screenWidth = MAX(_renderBufferWidth, _renderBufferHeight);
- screenHeight = MIN(_renderBufferWidth, _renderBufferHeight);
-// glOrthof(0, screenWidth, screenHeight, 0, 0, 1); printOpenGLError();
- }
- else {
- screenWidth = MIN(_renderBufferWidth, _renderBufferHeight);
- screenHeight = MAX(_renderBufferWidth, _renderBufferHeight);
-// glOrthof(0, screenHeight, screenWidth, 0, 0, 1); printOpenGLError();
+ [self setUpOrientation:[[UIDevice currentDevice] orientation] width:&screenWidth height:&screenHeight];
+
+ if (_screenTexture > 0) {
+ glDeleteTextures(1, &_screenTexture); printOpenGLError();
}
glGenTextures(1, &_screenTexture); printOpenGLError();
[self setFilterModeForTexture:_screenTexture];
+ if (_overlayTexture > 0) {
+ glDeleteTextures(1, &_overlayTexture); printOpenGLError();
+ }
+
glGenTextures(1, &_overlayTexture); printOpenGLError();
[self setFilterModeForTexture:_overlayTexture];
@@ -536,10 +482,10 @@ const char *iPhone_getDocumentsDir() {
[self clearColorBuffer];
-// if (_keyboardView != nil) {
-// [_keyboardView removeFromSuperview];
-// [[_keyboardView inputView] removeFromSuperview];
-// }
+ if (_keyboardView != nil) {
+ [_keyboardView removeFromSuperview];
+ [[_keyboardView inputView] removeFromSuperview];
+ }
GLfloat adjustedWidth = _videoContext.screenWidth;
GLfloat adjustedHeight = _videoContext.screenHeight;
@@ -552,7 +498,7 @@ const char *iPhone_getDocumentsDir() {
float overlayPortraitRatio;
- if (isLandscape) {
+ if (_orientation == UIDeviceOrientationLandscapeLeft || _orientation == UIDeviceOrientationLandscapeRight) {
GLfloat gameScreenRatio = adjustedWidth / adjustedHeight;
GLfloat screenRatio = (GLfloat)screenWidth / (GLfloat)screenHeight;
@@ -578,8 +524,6 @@ const char *iPhone_getDocumentsDir() {
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;
@@ -593,13 +537,14 @@ const char *iPhone_getDocumentsDir() {
if (_keyboardView == nil) {
_keyboardView = [[SoftKeyboard alloc] initWithFrame:keyFrame];
[_keyboardView setInputDelegate:self];
- [self addSubview:[_keyboardView inputView]];
- [self addSubview: _keyboardView];
}
- [_keyboardView showKeyboard];
+ [self addSubview:[_keyboardView inputView]];
+ [self addSubview: _keyboardView];
+ [[_keyboardView inputView] becomeFirstResponder];
overlayPortraitRatio = (_videoContext.overlayHeight * ratio) / _videoContext.overlayWidth;
}
+
_overlayRect = CGRectMake(0, 0, screenWidth, screenHeight * overlayPortraitRatio);
_gameScreenVertCoords[0] = _gameScreenVertCoords[4] = CGRectGetMinX(_gameScreenRect);
@@ -610,10 +555,6 @@ const char *iPhone_getDocumentsDir() {
_overlayVertCoords[2] = _overlayVertCoords[6] = CGRectGetMaxX(_overlayRect);
_overlayVertCoords[5] = _overlayVertCoords[7] = CGRectGetMaxY(_overlayRect);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glOrthof(0, screenWidth, screenHeight, 0, 0, 1);
-
[self setViewTransformation];
[self updateMouseCursorScaling];
}
@@ -660,12 +601,40 @@ const char *iPhone_getDocumentsDir() {
return true;
}
+/**
+ * Converts portrait mode coordinates into rotated mode coordinates.
+ */
+- (bool)convertToRotatedCoords:(CGPoint)point result:(CGPoint *)result {
+ switch (_orientation) {
+ case UIDeviceOrientationLandscapeLeft:
+ result->x = point.y;
+ result->y = _renderBufferWidth - point.x;
+ return true;
+
+ case UIDeviceOrientationLandscapeRight:
+ result->x = _renderBufferHeight - point.y;
+ result->y = point.x;
+ return true;
+
+ case UIDeviceOrientationPortrait:
+ result->x = point.x;
+ result->y = point.y;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
- (bool)getMouseCoords:(CGPoint)point eventX:(int *)x eventY:(int *)y {
// We scale the input according to our scale factor to get actual screen
// cooridnates.
point.x *= _contentScaleFactor;
point.y *= _contentScaleFactor;
+ if (![self convertToRotatedCoords:point result:&point])
+ return false;
+
CGRect *area;
int width, height, offsetY;
if (_videoContext.overlayVisible) {
@@ -688,58 +657,62 @@ const char *iPhone_getDocumentsDir() {
// thus we need to add it here.
*y = (int)(point.y * height + offsetY);
- if (!iphone_touchpadModeEnabled()) {
- // Clip coordinates
- if (*x < 0 || *x > width || *y < 0 || *y > height)
- return false;
- }
+ // 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)];
-}
+ switch (orientation) {
+ case UIDeviceOrientationLandscapeLeft:
+ case UIDeviceOrientationLandscapeRight:
+ case UIDeviceOrientationPortrait:
+ _orientation = orientation;
+ break;
-- (UITouch *)secondTouchOtherTouchThan:(UITouch *)touch in:(NSSet *)set {
- NSArray *all = [set allObjects];
- for (UITouch *t in all) {
- if (t != touch) {
- return t;
- }
+ default:
+ return;
}
- return nil;
+
+ [self addEvent:InternalEvent(kInputOrientationChanged, orientation, 0)];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+ NSSet *allTouches = [event allTouches];
int x, y;
- NSSet<UITouch *> *allTouches = [event allTouches];
- if (allTouches.count == 1) {
- _firstTouch = [allTouches anyObject];
- CGPoint point = [_firstTouch locationInView:self];
+ switch ([allTouches count]) {
+ case 1: {
+ UITouch *touch = [touches anyObject];
+ CGPoint point = [touch locationInView:self];
if (![self getMouseCoords:point eventX:&x eventY:&y])
return;
+ _firstTouch = touch;
[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;
+ break;
+ }
+
+ case 2: {
+ UITouch *touch = [touches anyObject];
+ CGPoint point = [touch locationInView:self];
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
+ return;
- [self addEvent:InternalEvent(kInputMouseSecondDown, x, y)];
+ _secondTouch = touch;
+ [self addEvent:InternalEvent(kInputMouseSecondDown, x, y)];
+ break;
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
+ //NSSet *allTouches = [event allTouches];
int x, y;
- NSSet<UITouch *> *allTouches = [event allTouches];
- for (UITouch *touch in allTouches) {
+ for (UITouch *touch in touches) {
if (touch == _firstTouch) {
CGPoint point = [touch locationInView:self];
if (![self getMouseCoords:point eventX:&x eventY:&y])
@@ -750,64 +723,55 @@ const char *iPhone_getDocumentsDir() {
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 {
+ NSSet *allTouches = [event allTouches];
int x, y;
- NSSet<UITouch *> *allTouches = [event allTouches];
- if (allTouches.count == 1) {
- UITouch *touch = [allTouches anyObject];
+ switch ([allTouches count]) {
+ case 1: {
+ UITouch *touch = [[allTouches allObjects] objectAtIndex:0];
CGPoint point = [touch locationInView:self];
- if (![self getMouseCoords:point eventX:&x eventY:&y]) {
+ if (![self getMouseCoords:point eventX:&x eventY:&y])
return;
- }
[self addEvent:InternalEvent(kInputMouseUp, x, y)];
- }
- else if (allTouches.count == 2) {
+ break;
+ }
+
+ case 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)];
+ break;
+ }
}
- _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)handleKeyPress:(unichar)c {
+ [self addEvent:InternalEvent(kInputKeyPressed, c, 0)];
}
-- (void)twoFingersSwipeDown:(UISwipeGestureRecognizer *)recognizer {
- [self addEvent:InternalEvent(kInputSwipe, kUIViewSwipeDown, 2)];
+- (BOOL)canHandleSwipes {
+ return TRUE;
}
-- (void)twoFingersDoubleTap:(UITapGestureRecognizer *)recognizer {
- [self addEvent:InternalEvent(kInputTap, kUIViewTapDouble, 2)];
-}
+- (int)swipe:(int)num withEvent:(struct __GSEvent *)event {
+ //printf("swipe: %i\n", num);
-- (void)handleKeyPress:(unichar)c {
- [self addEvent:InternalEvent(kInputKeyPressed, c, 0)];
+ [self addEvent:InternalEvent(kInputSwipe, num, 0)];
+ return 0;
}
- (void)applicationSuspend {
diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp
index 19da580c80..95ca25a2d2 100644
--- a/backends/platform/iphone/osys_events.cpp
+++ b/backends/platform/iphone/osys_events.cpp
@@ -64,17 +64,6 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
if (!handleEvent_mouseDragged(event, internalEvent.value1, internalEvent.value2))
return false;
break;
-
- case kInputOrientationChanged:
- handleEvent_orientationChanged(internalEvent.value1);
- return false;
- break;
-
- case kInputApplicationSuspended:
- suspendLoop();
- return false;
- break;
-
case kInputMouseSecondDragged:
if (!handleEvent_mouseSecondDragged(event, internalEvent.value1, internalEvent.value2))
return false;
@@ -89,25 +78,29 @@ bool OSystem_IPHONE::pollEvent(Common::Event &event) {
if (!handleEvent_secondMouseUp(event, internalEvent.value1, internalEvent.value2))
return false;
break;
-
+ case kInputOrientationChanged:
+ handleEvent_orientationChanged(internalEvent.value1);
+ return false;
+ break;
+
+ case kInputApplicationSuspended:
+ suspendLoop();
+ 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))
+ if (!handleEvent_swipe(event, internalEvent.value1))
return false;
break;
default:
break;
}
-
+
return true;
}
return false;
@@ -426,137 +419,71 @@ void OSystem_IPHONE::handleEvent_keyPressed(Common::Event &event, int keyPresse
_queuedEventTime = getMillis() + kQueuedInputEventDelay;
}
-bool OSystem_IPHONE::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;
- }
+bool OSystem_IPHONE::handleEvent_swipe(Common::Event &event, int direction) {
+ Common::KeyCode keycode = Common::KEYCODE_INVALID;
+ switch (_screenOrientation) {
+ case kScreenOrientationPortrait:
+ switch ((UIViewSwipeDirection)direction) {
+ case kUIViewSwipeUp:
+ keycode = Common::KEYCODE_UP;
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;
- }
+ case kUIViewSwipeDown:
+ keycode = Common::KEYCODE_DOWN;
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;
- }
+ case kUIViewSwipeLeft:
+ keycode = Common::KEYCODE_LEFT;
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();
+ case kUIViewSwipeRight:
+ keycode = Common::KEYCODE_RIGHT;
+ break;
+ default:
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();
+ 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;
}
-
- default:
+ 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;
}
- return false;
-}
-bool OSystem_IPHONE::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;
+ 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;
}
diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp
index ef3499d597..0ce21b44c1 100644
--- a/backends/platform/iphone/osys_main.cpp
+++ b/backends/platform/iphone/osys_main.cpp
@@ -38,8 +38,6 @@
#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"
@@ -65,11 +63,7 @@ OSystem_IPHONE::OSystem_IPHONE() :
_mouseCursorPaletteEnabled(false), _gfxTransactionError(kTransactionSuccess) {
_queuedInputEvent.type = Common::EVENT_INVALID;
_touchpadModeEnabled = !iPhone_isHighResDevice();
-#ifdef IPHONE_OFFICIAL
- _fsFactory = new ChRootFilesystemFactory(iPhone_getDocumentsDir());
-#else
_fsFactory = new POSIXFilesystemFactory();
-#endif
initVideoContext();
memset(_gamePalette, 0, sizeof(_gamePalette));
@@ -89,10 +83,6 @@ OSystem_IPHONE::~OSystem_IPHONE() {
_mouseBuffer.free();
}
-bool OSystem_IPHONE::touchpadModeEnabled() const {
- return _touchpadModeEnabled;
-}
-
int OSystem_IPHONE::timerHandler(int t) {
DefaultTimerManager *tm = (DefaultTimerManager *)g_system->getTimerManager();
tm->handler();
@@ -101,7 +91,7 @@ int OSystem_IPHONE::timerHandler(int t) {
void OSystem_IPHONE::initBackend() {
#ifdef IPHONE_OFFICIAL
- _savefileManager = new DefaultSaveFileManager("/Savegames");
+ _savefileManager = new DefaultSaveFileManager(iPhone_getDocumentsDir());
#else
_savefileManager = new DefaultSaveFileManager(SCUMMVM_SAVE_PATH);
#endif
@@ -263,7 +253,8 @@ OSystem *OSystem_IPHONE_create() {
Common::String OSystem_IPHONE::getDefaultConfigFileName() {
#ifdef IPHONE_OFFICIAL
- Common::String path = "/Preferences";
+ Common::String path = iPhone_getDocumentsDir();
+ path += "/Preferences";
return path;
#else
return SCUMMVM_PREFS_PATH;
@@ -279,14 +270,7 @@ void OSystem_IPHONE::addSysArchivesToSearchSet(Common::SearchSet &s, int priorit
if (CFURLGetFileSystemRepresentation(fileUrl, true, buf, sizeof(buf))) {
// Success: Add it to the search path
Common::String bundlePath((const char *)buf);
-#ifdef IPHONE_OFFICIAL
- POSIXFilesystemNode *posixNode = new POSIXFilesystemNode(bundlePath);
- Common::FSNode *node = new Common::FSNode(posixNode);
- s.add("__OSX_BUNDLE__", new Common::FSDirectory(*node), priority);
-#else
- // OS X
s.add("__OSX_BUNDLE__", new Common::FSDirectory(bundlePath), priority);
-#endif
}
CFRelease(fileUrl);
}
@@ -304,11 +288,6 @@ void OSystem_IPHONE::logMessage(LogMessageType::Type type, const char *message)
fflush(output);
}
-bool iphone_touchpadModeEnabled() {
- OSystem_IPHONE *sys = (OSystem_IPHONE *) g_system;
- return sys && sys->touchpadModeEnabled();
-}
-
void iphone_main(int argc, char *argv[]) {
//OSystem_IPHONE::migrateApp();
diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h
index 04a531613f..0159eee1be 100644
--- a/backends/platform/iphone/osys_main.h
+++ b/backends/platform/iphone/osys_main.h
@@ -131,8 +131,6 @@ public:
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;
@@ -206,8 +204,7 @@ protected:
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);
+ bool handleEvent_swipe(Common::Event &event, int direction);
void handleEvent_keyPressed(Common::Event &event, int keyPressed);
void handleEvent_orientationChanged(int orientation);
diff --git a/configure b/configure
index cf70f8cb5f..b3008a13d6 100755
--- a/configure
+++ b/configure
@@ -835,7 +835,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:
@@ -875,7 +875,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
@@ -1362,6 +1363,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
@@ -2698,9 +2704,18 @@ if test -n "$_host"; then
;;
iphone)
append_var DEFINES "-DIPHONE"
+ append_var ASFLAGS "-arch armv6"
+ _backend="iphone"
+ _build_scalers=no
+ _mt32emu=no
+ _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="iphone"
+ _backend="ios7"
_build_scalers=no
_mt32emu=no
_seq_midi=no
@@ -3001,13 +3016,18 @@ case $_backend in
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"
+ ;;
+ 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 "-isysroot $SDKROOT"
- append_var CFLAGS "-isysroot $SDKROOT"
- append_var CXXFLAGS "-isysroot $SDKROOT"
+ append_var LDFLAGS "-isysroot $SDKROOT -I $SDKROOT/usr/include"
+ append_var CFLAGS "-isysroot $SDKROOT -I $SDKROOT/usr/include"
+ append_var CXXFLAGS "-isysroot $SDKROOT -I $SDKROOT/usr/include"
fi
;;
linuxmoto)
@@ -3144,7 +3164,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
@@ -3203,7 +3223,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/xcode.cpp b/devtools/create_project/xcode.cpp
index 2914920fd3..8365114863 100644
--- a/devtools/create_project/xcode.cpp
+++ b/devtools/create_project/xcode.cpp
@@ -96,7 +96,7 @@ bool targetIsIOS(const std::string &targetName) {
bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targetName, const std::string &fileName) {
// Rules:
- // - if the parent directory is "backends/platform/iphone", the file belongs to the iOS target.
+ // - 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.
@@ -133,7 +133,7 @@ bool shouldSkipFileForTarget(const std::string &fileID, const std::string &targe
}
// parent directory
const std::string directory = fileID.substr(0, fileID.length() - fileName.length());
- static const std::string iphone_directory = "backends/platform/iphone";
+ 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;
}
@@ -262,7 +262,7 @@ XcodeProvider::XcodeProvider(StringList &global_warnings, std::map<std::string,
}
void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includeList, StringList &excludeList) {
- includeList.push_back(setup.srcDir + "/dists/iphone/Info.plist");
+ includeList.push_back(setup.srcDir + "/dists/ios7/Info.plist");
ValueList &resources = getResourceFiles();
for (ValueList::iterator it = resources.begin(); it != resources.end(); ++it) {
@@ -270,7 +270,7 @@ void XcodeProvider::addResourceFiles(const BuildSetup &setup, StringList &includ
}
StringList td;
- createModuleList(setup.srcDir + "/backends/platform/iphone", setup.defines, td, includeList, excludeList);
+ createModuleList(setup.srcDir + "/backends/platform/ios7", setup.defines, td, includeList, excludeList);
}
void XcodeProvider::createWorkspace(const BuildSetup &setup) {
@@ -765,7 +765,7 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "\"");
iPhone_HeaderSearchPaths.push_back("\"" + projectOutputDirectory + "/include\"");
ADD_SETTING_LIST(iPhone_Debug, "HEADER_SEARCH_PATHS", iPhone_HeaderSearchPaths, SettingsAsList|SettingsQuoteVariable, 5);
- ADD_SETTING_QUOTE(iPhone_Debug, "INFOPLIST_FILE", "$(SRCROOT)/dists/iphone/Info.plist");
+ 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\"");
@@ -958,7 +958,7 @@ void XcodeProvider::setupBuildConfiguration(const BuildSetup &setup) {
void XcodeProvider::setupImageAssetCatalog(const BuildSetup &setup) {
const std::string filename = "Images.xcassets";
- const std::string absoluteCatalogPath = _projectRoot + "/dists/iphone/" + filename;
+ const std::string absoluteCatalogPath = _projectRoot + "/dists/ios7/" + filename;
const std::string id = "FileReference_" + absoluteCatalogPath;
Group *group = touchGroupsForPath(absoluteCatalogPath);
group->addChildFile(filename);
@@ -967,7 +967,7 @@ void XcodeProvider::setupImageAssetCatalog(const BuildSetup &setup) {
void XcodeProvider::setupAdditionalSources(std::string targetName, Property &files, int &order) {
if (targetIsIOS(targetName)) {
- const std::string absoluteCatalogPath = _projectRoot + "/dists/iphone/Images.xcassets";
+ const std::string absoluteCatalogPath = _projectRoot + "/dists/ios7/Images.xcassets";
ADD_SETTING_ORDER_NOVALUE(files, getHash(absoluteCatalogPath), "Image Asset Catalog", order++);
}
}
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/Contents.json b/dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json
index 607a2a141a..607a2a141a 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/Contents.json
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/Contents.json
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png
index 9b89d07046..9b89d07046 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png
index 0de0984ed7..0de0984ed7 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png
index db6089dcf6..db6089dcf6 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png
index 9a7575b404..9a7575b404 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png
index 5cd982d0e1..5cd982d0e1 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png
index 22580b0ac6..22580b0ac6 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png
index 22580b0ac6..22580b0ac6 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png
index c5f39976bb..c5f39976bb 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png
index 0609594553..0609594553 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png
index 7bc1ae1de1..7bc1ae1de1 100644
--- a/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png
+++ b/dists/ios7/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/Contents.json b/dists/ios7/Images.xcassets/Contents.json
index da4a164c91..da4a164c91 100644
--- a/dists/iphone/Images.xcassets/Contents.json
+++ b/dists/ios7/Images.xcassets/Contents.json
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/Contents.json b/dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json
index 139f4e7756..139f4e7756 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/Contents.json
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/Contents.json
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
index 6fb6c9bf4b..6fb6c9bf4b 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
index 8d6e588226..8d6e588226 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
index 988122bce8..988122bce8 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
index 91641cf91f..91641cf91f 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
+++ b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png
Binary files differ
diff --git a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png b/dists/ios7/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png
index 6a33b63110..6a33b63110 100644
--- a/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png
+++ 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..3735919321
--- /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>UILaunchImages</key>
+ <array/>
+ <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>
+ <true/>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <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..c179ffed8f
--- /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>UILaunchImages</key>
+ <array/>
+ <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>
+ <true/>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <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/iphone/Default.png b/dists/iphone/Default.png
new file mode 100644
index 0000000000..7570bc27d1
--- /dev/null
+++ b/dists/iphone/Default.png
Binary files differ
diff --git a/dists/iphone/Info.plist b/dists/iphone/Info.plist
index 3735919321..d630801504 100644
--- a/dists/iphone/Info.plist
+++ b/dists/iphone/Info.plist
@@ -6,14 +6,8 @@
<string>en</string>
<key>CFBundleExecutable</key>
<string>ScummVM</string>
- <key>CFBundleIcons</key>
- <dict/>
- <key>CFBundleIcons~ipad</key>
- <dict/>
- <key>UILaunchImages</key>
- <array/>
<key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <string>org.scummvm.scummvm</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -26,27 +20,26 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>1.8.0git</string>
- <key>UIApplicationExitsOnSuspend</key>
- <true/>
- <key>UIFileSharingEnabled</key>
- <true/>
+ <key>CFBundleIconFile</key>
+ <string>icon.png</string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>icon.png</string>
+ <string>icon-72.png</string>
+ <string>icon4.png</string>
+ </array>
<key>UIPrerenderedIcon</key>
<true/>
- <key>UIRequiresFullScreen</key>
- <true/>
- <key>UIStatusBarHidden</key>
- <true/>
- <key>UISupportedInterfaceOrientations</key>
+ <key>UIDeviceFamily</key>
<array>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- <string>UIInterfaceOrientationPortrait</string>
+ <integer>1</integer>
+ <integer>2</integer>
</array>
- <key>UISupportedInterfaceOrientations~ipad</key>
+ <key>UISupportedInterfaceOrientations</key>
<array>
+ <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
- <string>UIInterfaceOrientationPortrait</string>
</array>
</dict>
</plist>
diff --git a/dists/iphone/Info.plist.in b/dists/iphone/Info.plist.in
index c179ffed8f..2bcdd15a03 100644
--- a/dists/iphone/Info.plist.in
+++ b/dists/iphone/Info.plist.in
@@ -6,14 +6,8 @@
<string>en</string>
<key>CFBundleExecutable</key>
<string>ScummVM</string>
- <key>CFBundleIcons</key>
- <dict/>
- <key>CFBundleIcons~ipad</key>
- <dict/>
- <key>UILaunchImages</key>
- <array/>
<key>CFBundleIdentifier</key>
- <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
+ <string>org.scummvm.scummvm</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -26,27 +20,26 @@
<string>????</string>
<key>CFBundleVersion</key>
<string>@VERSION@</string>
- <key>UIApplicationExitsOnSuspend</key>
- <true/>
- <key>UIFileSharingEnabled</key>
- <true/>
+ <key>CFBundleIconFile</key>
+ <string>icon.png</string>
+ <key>CFBundleIconFiles</key>
+ <array>
+ <string>icon.png</string>
+ <string>icon-72.png</string>
+ <string>icon4.png</string>
+ </array>
<key>UIPrerenderedIcon</key>
<true/>
- <key>UIRequiresFullScreen</key>
- <true/>
- <key>UIStatusBarHidden</key>
- <true/>
- <key>UISupportedInterfaceOrientations</key>
+ <key>UIDeviceFamily</key>
<array>
- <string>UIInterfaceOrientationLandscapeLeft</string>
- <string>UIInterfaceOrientationLandscapeRight</string>
- <string>UIInterfaceOrientationPortrait</string>
+ <integer>1</integer>
+ <integer>2</integer>
</array>
- <key>UISupportedInterfaceOrientations~ipad</key>
+ <key>UISupportedInterfaceOrientations</key>
<array>
+ <string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
- <string>UIInterfaceOrientationPortrait</string>
</array>
</dict>
</plist>
diff --git a/dists/iphone/icon-72.png b/dists/iphone/icon-72.png
new file mode 100644
index 0000000000..9b424b4018
--- /dev/null
+++ b/dists/iphone/icon-72.png
Binary files differ
diff --git a/dists/iphone/icon.png b/dists/iphone/icon.png
new file mode 100644
index 0000000000..3c96b0dee4
--- /dev/null
+++ b/dists/iphone/icon.png
Binary files differ
diff --git a/dists/iphone/icon4.png b/dists/iphone/icon4.png
new file mode 100644
index 0000000000..5abe16ed51
--- /dev/null
+++ b/dists/iphone/icon4.png
Binary files differ
diff --git a/ports.mk b/ports.mk
index 143674b8f9..fecce3b36b 100644
--- a/ports.mk
+++ b/ports.mk
@@ -78,6 +78,28 @@ endif
iphonebundle: iphone
mkdir -p $(bundle_name)
+ cp $(srcdir)/dists/iphone/Info.plist $(bundle_name)/
+ 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/iphone/icon.png $(bundle_name)/
+ cp $(srcdir)/dists/iphone/icon-72.png $(bundle_name)/
+ cp $(srcdir)/dists/iphone/Default.png $(bundle_name)/
+ # Binary patch workaround for Iphone 5/IPad 4 "Illegal instruction: 4" toolchain issue (http://code.google.com/p/iphone-gcc-full/issues/detail?id=6)
+ cp scummvm scummvm-iph5
+ sed -i'' 's/\x00\x30\x93\xe4/\x00\x30\x93\xe5/g;s/\x00\x30\xd3\xe4/\x00\x30\xd3\xe5/g;' scummvm-iph5
+ ldid -S scummvm-iph5
+ chmod 755 scummvm-iph5
+ cp scummvm-iph5 $(bundle_name)/ScummVM-iph5
+
+ios7bundle: ios7
+ mkdir -p $(bundle_name)
awk 'BEGIN {s=0}\
/<key>CFBundleIcons<\/key>/ {\
print $$0;\
@@ -144,7 +166,7 @@ iphonebundle: iphone
print "\t</array>";\
s=2}\
s==0 {print $$0}\
- s > 0 { s-- }' $(srcdir)/dists/iphone/Info.plist >$(bundle_name)/Info.plist
+ 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)/
@@ -155,29 +177,23 @@ endif
ldid -S scummvm
chmod 755 scummvm
cp scummvm $(bundle_name)/ScummVM
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png $(bundle_name)/AppIcon29x29@2x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@2x.png $(bundle_name)/AppIcon29x29@2x~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29@3x.png $(bundle_name)/AppIcon29x29@3x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-29.png $(bundle_name)/AppIcon29x29~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png $(bundle_name)/AppIcon40x40@2x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@2x.png $(bundle_name)/AppIcon40x40@2x~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40@3x.png $(bundle_name)/AppIcon40x40@3x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-40.png $(bundle_name)/AppIcon40x40~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@2x.png $(bundle_name)/AppIcon60x60@2x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-60@3x.png $(bundle_name)/AppIcon60x60@3x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76@2x.png $(bundle_name)/AppIcon76x76@2x~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/AppIcon.appiconset/icon4-76.png $(bundle_name)/AppIcon76x76~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-640x1136-1.png $(bundle_name)/LaunchImage-700-568h@2x.png
- cp $(srcdir)/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-2048x1536.png $(bundle_name)/LaunchImage-700-Landscape@2x~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1024x768.png $(bundle_name)/LaunchImage-700-Landscape~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-1536x2048.png $(bundle_name)/LaunchImage-700-Portrait@2x~ipad.png
- cp $(srcdir)/dists/iphone/Images.xcassets/LaunchImage.launchimage/ScummVM-splash-768x1024.png $(bundle_name)/LaunchImage-700-Portrait~ipad.png
- # Binary patch workaround for Iphone 5/IPad 4 "Illegal instruction: 4" toolchain issue (http://code.google.com/p/iphone-gcc-full/issues/detail?id=6)
- cp scummvm scummvm-iph5
- sed -i'' 's/\x00\x30\x93\xe4/\x00\x30\x93\xe5/g;s/\x00\x30\xd3\xe4/\x00\x30\xd3\xe5/g;' scummvm-iph5
- ldid -S scummvm-iph5
- chmod 755 scummvm-iph5
- cp scummvm-iph5 $(bundle_name)/ScummVM-iph5
+ 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/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
# Location of static libs for the iPhone
ifneq ($(BACKEND), iphone)
@@ -259,6 +275,13 @@ iphone: $(OBJS)
-framework CoreFoundation -framework QuartzCore -framework Foundation \
-framework AudioToolbox -framework CoreAudio -lobjc -lz
+ios7: $(OBJS)
+ $(CXX) $(LDFLAGS) -o scummvm $(OBJS) \
+ $(OSX_STATIC_LIBS) \
+ -framework UIKit -framework CoreGraphics -framework OpenGLES \
+ -framework CoreFoundation -framework QuartzCore -framework Foundation \
+ -framework AudioToolbox -framework CoreAudio -lobjc -lz
+
# Special target to create a snapshot disk image for Mac OS X
# TODO: Replace AUTHORS by Credits.rtf
osxsnap: bundle