IOS: Create two targets for old iPhone (iOS <= 6) and new one (iOS >= 7)

The "iphone" backend is the support for the old iPhones.
The "ios7" backend is for the new iPhones.
This commit is contained in:
Vincent Bénony 2015-12-04 18:20:09 +01:00
parent 124d37247b
commit 638dc113f8
51 changed files with 3591 additions and 523 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)))

View File

@ -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;
}

View File

@ -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!
}

View File

@ -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

View File

@ -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);
}

View File

@ -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];
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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;

View File

@ -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];
_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];
g_fullWidth = (int)MAX(frame.size.width, frame.size.height);
g_fullHeight = (int)MIN(frame.size.width, frame.size.height);
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,6 +412,44 @@ const char *iPhone_getDocumentsDir() {
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();
}
- (void)setUpOrientation:(UIDeviceOrientation)orientation width:(int *)width height:(int *)height {
_orientation = orientation;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// 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();
*width = _renderBufferHeight;
*height = _renderBufferWidth;
break;
case UIDeviceOrientationLandscapeLeft:
glRotatef(-90, 0, 0, 1); printOpenGLError();
glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError();
*width = _renderBufferHeight;
*height = _renderBufferWidth;
break;
case UIDeviceOrientationPortrait:
default:
// We must force the portrait orientation here, since we might not know
// the real orientation.
_orientation = UIDeviceOrientationPortrait;
glOrthof(0, _renderBufferWidth, _renderBufferHeight, 0, 0, 1); printOpenGLError();
*width = _renderBufferWidth;
*height = _renderBufferHeight;
break;
}
}
- (void)createScreenTexture {
const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth);
const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight);
@ -474,61 +461,20 @@ const char *iPhone_getDocumentsDir() {
}
- (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();
[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 {
switch (orientation) {
case UIDeviceOrientationLandscapeLeft:
case UIDeviceOrientationLandscapeRight:
case UIDeviceOrientationPortrait:
_orientation = orientation;
break;
default:
return;
}
[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 {
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;
}
[self addEvent:InternalEvent(kInputMouseSecondDown, x, y)];
case 2: {
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
if (![self getMouseCoords:point eventX:&x eventY:&y])
return;
_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,66 +723,57 @@ 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)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)];
}
- (BOOL)canHandleSwipes {
return TRUE;
}
- (int)swipe:(int)num withEvent:(struct __GSEvent *)event {
//printf("swipe: %i\n", num);
[self addEvent:InternalEvent(kInputSwipe, num, 0)];
return 0;
}
- (void)applicationSuspend {
[self addEvent:InternalEvent(kInputApplicationSuspended, 0, 0)];
}

View File

@ -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;
}
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) {
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: {
_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:
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;
}
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;
}

View File

@ -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();

View File

@ -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);

36
configure vendored
View File

@ -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
@ -2697,10 +2703,19 @@ if test -n "$_host"; then
_port_mk="backends/platform/gph/gp2xwiz-bundle.mk"
;;
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
@ -2998,6 +3013,11 @@ case $_backend in
fi
;;
iphone)
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"
@ -3005,9 +3025,9 @@ case $_backend in
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*)

View File

@ -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++);
}
}

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 33 KiB

View File

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

52
dists/ios7/Info.plist Normal file
View File

@ -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>

52
dists/ios7/Info.plist.in Normal file
View File

@ -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>

BIN
dists/iphone/Default.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -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>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<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>

View File

@ -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>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<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>

BIN
dists/iphone/icon-72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
dists/iphone/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
dists/iphone/icon4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -77,6 +77,28 @@ endif
$(STRIP) $(bundle_name)/Contents/MacOS/scummvm
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>/ {\
@ -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