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.
111
backends/platform/ios7/iphone_common.h
Normal 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
|
44
backends/platform/ios7/iphone_keyboard.h
Normal 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
|
98
backends/platform/ios7/iphone_keyboard.mm
Normal 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
|
154
backends/platform/ios7/iphone_main.mm
Normal 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
|
109
backends/platform/ios7/iphone_video.h
Normal 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
|
821
backends/platform/ios7/iphone_video.mm
Normal 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
|
15
backends/platform/ios7/module.mk
Normal 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)))
|
562
backends/platform/ios7/osys_events.cpp
Normal 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;
|
||||
}
|
344
backends/platform/ios7/osys_main.cpp
Normal 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(¤tTime, 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!
|
||||
}
|
224
backends/platform/ios7/osys_main.h
Normal 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
|
105
backends/platform/ios7/osys_sound.cpp
Normal 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);
|
||||
}
|
503
backends/platform/ios7/osys_video.mm
Normal 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];
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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)];
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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
@ -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*)
|
||||
|
@ -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++);
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 9.9 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 234 KiB After Width: | Height: | Size: 234 KiB |
Before Width: | Height: | Size: 921 KiB After Width: | Height: | Size: 921 KiB |
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 1.0 MiB |
Before Width: | Height: | Size: 656 KiB After Width: | Height: | Size: 656 KiB |
Before Width: | Height: | Size: 181 KiB After Width: | Height: | Size: 181 KiB |
52
dists/ios7/Info.plist
Normal 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
@ -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
After Width: | Height: | Size: 32 KiB |
@ -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>
|
||||
|
@ -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
After Width: | Height: | Size: 9.5 KiB |
BIN
dists/iphone/icon.png
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
dists/iphone/icon4.png
Normal file
After Width: | Height: | Size: 16 KiB |
71
ports.mk
@ -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
|
||||
|