diff options
author | Oystein Eftevaag | 2007-11-13 08:06:15 +0000 |
---|---|---|
committer | Oystein Eftevaag | 2007-11-13 08:06:15 +0000 |
commit | 05b5a493f85350ec5df86dc95045fee6e193ed27 (patch) | |
tree | 84ad89c3bcc76e82b4e80281850411b0507f4351 /backends | |
parent | c908a8a73fe5d908c23208fc259d16b647c09d56 (diff) | |
download | scummvm-rg350-05b5a493f85350ec5df86dc95045fee6e193ed27.tar.gz scummvm-rg350-05b5a493f85350ec5df86dc95045fee6e193ed27.tar.bz2 scummvm-rg350-05b5a493f85350ec5df86dc95045fee6e193ed27.zip |
Initial commit of the iPhone/iPod Touch backend
svn-id: r29488
Diffstat (limited to 'backends')
-rw-r--r-- | backends/platform/iphone/iphone_common.h | 52 | ||||
-rw-r--r-- | backends/platform/iphone/iphone_main.m | 96 | ||||
-rw-r--r-- | backends/platform/iphone/iphone_video.h | 61 | ||||
-rw-r--r-- | backends/platform/iphone/iphone_video.m | 318 | ||||
-rw-r--r-- | backends/platform/iphone/module.mk | 12 | ||||
-rw-r--r-- | backends/platform/iphone/osys_iphone.cpp | 621 | ||||
-rw-r--r-- | backends/platform/iphone/osys_iphone.h | 144 |
7 files changed, 1304 insertions, 0 deletions
diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h new file mode 100644 index 0000000000..f1731f3dfe --- /dev/null +++ b/backends/platform/iphone/iphone_common.h @@ -0,0 +1,52 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + + +enum InputEvent { + kInputMouseDown, + kInputMouseUp, + kInputMouseDragged, + kInputMouseSecondToggled +}; + +// We need this to be able to call functions from/in Objective-C. +#ifdef __cplusplus +extern "C" { +#endif + +// On the C++ side +void iphone_main(int argc, char *argv[]); + +// On the ObjC side +void iPhone_updateScreen(); +unsigned short* iPhone_getSurface(); +void iPhone_lockSurface(); +void iPhone_unlockSurface(); +void iPhone_initSurface(int width, int height); +bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY); + +#ifdef __cplusplus +} +#endif diff --git a/backends/platform/iphone/iphone_main.m b/backends/platform/iphone/iphone_main.m new file mode 100644 index 0000000000..5701b361ff --- /dev/null +++ b/backends/platform/iphone/iphone_main.m @@ -0,0 +1,96 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#import <UIKit/UIKit.h> +#import <Foundation/NSThread.h> +#include "iphone_video.h" + +void iphone_main(int argc, char *argv[]); + +@interface iPhoneMain : UIApplication { + UIWindow* _window; + iPhoneView* _view; +} + +- (void) mainLoop: (id)param; +- (iPhoneView*) getView; +- (UIWindow*) getWindow; +@end + +static int gArgc; +static char** gArgv; + +int main(int argc, char** argv) { + gArgc = argc; + gArgv = argv; + + [[NSAutoreleasePool alloc] init]; + + return UIApplicationMain(argc, argv, [iPhoneMain class]); +} + +@implementation iPhoneMain + +-(id) init { + [super init]; + _window = nil; + _view = nil; + return self; +} + +- (void) mainLoop: (id)param { + [[NSAutoreleasePool alloc] init]; + + iphone_main(gArgc, gArgv); + [UIApp terminate]; +} + +- (iPhoneView*) getView { + return _view; +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + // hide the status bar + [UIHardware _setStatusBarHeight:0.0f]; + [self setStatusBarMode:2 orientation:0 duration:0.0f fenceID:0]; + + _window = [[UIWindow alloc] initWithContentRect: [UIHardware fullScreenApplicationContentRect]]; + [_window retain]; + + _view = [[iPhoneView alloc] initWithFrame: [UIHardware fullScreenApplicationContentRect]]; + [_window setContentView: _view]; + + [_window orderFront: self]; + [_window makeKey: self]; + + [NSThread detachNewThreadSelector:@selector(mainLoop:) toTarget:self withObject:nil]; +} + +- (UIWindow*) getWindow { + return _window; +} + +@end + diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h new file mode 100644 index 0000000000..dfd45eb89a --- /dev/null +++ b/backends/platform/iphone/iphone_video.h @@ -0,0 +1,61 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifndef _IPHONE_VIDEO__H +#define _IPHONE_VIDEO__H + +#import <UIKit/UIKit.h> +#import <UIKit/UIView-Geometry.h> +#import <GraphicsServices/GraphicsServices.h> +#import <Foundation/Foundation.h> +#import <CoreSurface/CoreSurface.h> +#import <LayerKit/LKLayer.h> + + +@interface iPhoneView : UIView +{ + CoreSurfaceBufferRef _screenSurface; + NSMutableArray* _events; + NSLock* _lock; + int _fullWidth; + int _fullHeight; + int _widthOffset; + int _heightOffset; +} + +- (id)initWithFrame:(struct CGRect)frame; + +- (void)drawRect:(CGRect)frame; + +- (CoreSurfaceBufferRef)getSurface; + +- (void)initSurface; + +- (void)updateScreen; + +- (id)getEvent; +@end + +#endif /* _IPHONE_VIDEO__H */ diff --git a/backends/platform/iphone/iphone_video.m b/backends/platform/iphone/iphone_video.m new file mode 100644 index 0000000000..becd30b7d7 --- /dev/null +++ b/backends/platform/iphone/iphone_video.m @@ -0,0 +1,318 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#include "iphone_video.h" +#include "iphone_common.h" + +#import <UIKit/UIKit.h> +#import <UIKit/UIView-Geometry.h> +#import <GraphicsServices/GraphicsServices.h> +#import <Foundation/Foundation.h> +#import <CoreSurface/CoreSurface.h> +#import <LayerKit/LKLayer.h> + +static iPhoneView *sharedInstance = nil; +static int _width = 0; +static int _height = 0; + +// static long lastTick = 0; +// static int frames = 0; + +unsigned short* iPhone_getSurface() { + return CoreSurfaceBufferGetBaseAddress([sharedInstance getSurface]); +} + +void iPhone_updateScreen() { + [sharedInstance performSelectorOnMainThread:@selector(updateScreen) withObject:nil waitUntilDone: NO]; +} + +void iPhone_lockSurface() { + CoreSurfaceBufferLock([sharedInstance getSurface], 3); +} + +void iPhone_unlockSurface() { + CoreSurfaceBufferUnlock([sharedInstance getSurface]); +} + +void iPhone_initSurface(int width, int height) { + _width = width; + _height = height; + + [sharedInstance performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES]; +} + +bool iPhone_fetchEvent(int *outEvent, float *outX, float *outY) +{ + id event = [sharedInstance getEvent]; + if (event == nil) { + return false; + } + + id type = [event objectForKey:@"type"]; + + if (type == nil) { + printf("fetchEvent says: No type!\n"); + return false; + } + + *outEvent = [type intValue]; + *outX = [[event objectForKey:@"x"] floatValue]; + *outY = [[event objectForKey:@"y"] floatValue]; + return true; +} + +@implementation iPhoneView + +- (id)initWithFrame:(struct CGRect)frame { + [super initWithFrame: frame]; + + _fullWidth = frame.size.width; + _fullHeight = frame.size.height; + + sharedInstance = self; + + return self; +} + +-(void) dealloc { + [super dealloc]; +} + +- (CoreSurfaceBufferRef)getSurface { + return _screenSurface; +} + +- (void)drawRect:(CGRect)frame { + // if (lastTick == 0) { + // lastTick = time(0); + // } + // + // frames++; + // if (time(0) > lastTick) { + // lastTick = time(0); + // printf("FPS: %i\n", frames); + // frames = 0; + // } +} + +- (void)updateScreen { + [sharedInstance setNeedsDisplay]; +} + +- (void)initSurface { + //printf("Window: (%d, %d), Surface: (%d, %d)\n", _fullWidth, _fullHeight, _width, _height); + + int pitch = _width * 2; + int allocSize = 2 * _width * _height; + char *pixelFormat = "565L"; + + NSDictionary* dict = [[NSDictionary alloc] initWithObjectsAndKeys: + kCFBooleanTrue, kCoreSurfaceBufferGlobal, + @"PurpleGFXMem", kCoreSurfaceBufferMemoryRegion, + [NSNumber numberWithInt: pitch], kCoreSurfaceBufferPitch, + [NSNumber numberWithInt: _width], kCoreSurfaceBufferWidth, + [NSNumber numberWithInt: _height], kCoreSurfaceBufferHeight, + [NSNumber numberWithInt: *(int*)pixelFormat], kCoreSurfaceBufferPixelFormat, + [NSNumber numberWithInt: allocSize], kCoreSurfaceBufferAllocSize, + nil + ]; + + //("Allocating surface: %d\n", allocSize); + _screenSurface = CoreSurfaceBufferCreate((CFDictionaryRef)dict); + //printf("Surface created.\n"); + CoreSurfaceBufferLock(_screenSurface, 3); + + LKLayer* screenLayer = [[LKLayer layer] retain]; + + float ratioDifference = ((float)_width / (float)_height) / ((float)_fullWidth / (float)_fullHeight); + int rectWidth, rectHeight; + if (ratioDifference < 1.0f) { + rectWidth = _fullWidth * ratioDifference; + rectHeight = _fullHeight; + _widthOffset = (_fullWidth - rectWidth)/2; + _heightOffset = 0; + } else { + rectWidth = _fullWidth; + rectHeight = _fullHeight / ratioDifference; + _heightOffset = (_fullHeight - rectHeight)/2; + _widthOffset = 0; + } + + //printf("Rect: %i, %i, %i, %i\n", _widthOffset, _heightOffset, rectWidth + _widthOffset, rectHeight + _heightOffset); + [screenLayer setFrame: CGRectMake(_widthOffset, _heightOffset, rectWidth + _widthOffset, rectHeight + _heightOffset)]; + + [screenLayer setContents: _screenSurface]; + [screenLayer setOpaque: YES]; + [[sharedInstance _layer] addSublayer: screenLayer]; + + CoreSurfaceBufferUnlock(_screenSurface); + [dict release]; +} + + +- (void)lock +{ + [_lock lock]; +} + +- (void)unlock +{ + [_lock unlock]; +} + +- (id)getEvent +{ + if (_events == nil || [_events count] == 0) { + return nil; + } + + [self lock]; + + id event = [_events objectAtIndex: 0]; + if (event == nil) { + return nil; + } + + [_events removeObjectAtIndex: 0]; + [self unlock]; + + return event; +} + +- (void)addEvent:(NSDictionary*)event +{ + [self lock]; + + if(_events == nil) + _events = [[NSMutableArray alloc] init]; + + [_events addObject: event]; + + [self unlock]; +} + +- (void)mouseDown:(GSEvent*)event +{ + struct CGPoint point = GSEventGetLocationInWindow(event); + + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInt:kInputMouseDown], @"type", + [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x", + [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y", + nil + ] + ]; +} + +- (void)mouseUp:(GSEvent*)event +{ + struct CGPoint point = GSEventGetLocationInWindow(event); + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInt:kInputMouseUp], @"type", + [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x", + [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y", + nil + ] + ]; +} + +- (void)mouseDragged:(GSEvent*)event +{ + struct CGPoint point = GSEventGetLocationInWindow(event); + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInt:kInputMouseDragged], @"type", + [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x", + [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y", + nil + ] + ]; +} + +- (void)mouseEntered:(GSEvent*)event +{ + //printf("mouseEntered()\n"); + // struct CGPoint point = GSEventGetLocationInWindow(event); + // [self addEvent: + // [[NSDictionary alloc] initWithObjectsAndKeys: + // [NSNumber numberWithInt:kInputMouseSecondStartDrag], @"type", + // [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x", + // [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y", + // nil + // ] + // ]; +} + +- (void)mouseExited:(GSEvent*)event +{ + //printf("mouseExited().\n"); + // [self addEvent: + // [[NSDictionary alloc] initWithObjectsAndKeys: + // @"mouseExited", @"type", + // nil + // ] + // ]; +} + +- (void)mouseMoved:(GSEvent*)event +{ + //printf("mouseMoved()\n"); + struct CGPoint point = GSEventGetLocationInWindow(event); + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + [NSNumber numberWithInt:kInputMouseSecondToggled], @"type", + [NSNumber numberWithFloat:(point.x/_fullWidth)], @"x", + [NSNumber numberWithFloat:(point.y/_fullHeight)], @"y", + nil + ] + ]; +} + +- (void)keyDown:(GSEvent*)event +{ + printf("keyDown()\n"); + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + @"keyDown", @"type", + nil + ] + ]; +} + +- (void)keyUp:(GSEvent*)event +{ + printf("keyUp()\n"); + [self addEvent: + [[NSDictionary alloc] initWithObjectsAndKeys: + @"keyUp", @"type", + nil + ] + ]; +} + +@end + diff --git a/backends/platform/iphone/module.mk b/backends/platform/iphone/module.mk new file mode 100644 index 0000000000..2d26c26e59 --- /dev/null +++ b/backends/platform/iphone/module.mk @@ -0,0 +1,12 @@ +MODULE := backends/platform/iphone + +MODULE_OBJS := \ + osys_iphone.o \ + iphone_main.o \ + iphone_video.o + +MODULE_DIRS += \ + backends/platform/iphone/ + +# We don't use the rules.mk here on purpose +OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS) diff --git a/backends/platform/iphone/osys_iphone.cpp b/backends/platform/iphone/osys_iphone.cpp new file mode 100644 index 0000000000..7cf4ecffb0 --- /dev/null +++ b/backends/platform/iphone/osys_iphone.cpp @@ -0,0 +1,621 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#if defined(IPHONE_BACKEND) + +#include <CoreGraphics/CGDirectDisplay.h> +#include <CoreSurface/CoreSurface.h> +#include <unistd.h> +#include <pthread.h> + +#include "common/system.h" +#include "common/scummsys.h" +#include "common/util.h" +#include "common/rect.h" +#include "common/events.h" + +#include "base/main.h" + +#include "backends/saves/default/default-saves.h" +#include "backends/timer/default/default-timer.h" +#include "backends/intern.h" +#include "sound/mixer.h" + +#include "osys_iphone.h" +#include "iphone_common.h" + +const OSystem::GraphicsMode OSystem_IPHONE::s_supportedGraphicsModes[] = { + {0, 0, 0} +}; + +OSystem_IPHONE::OSystem_IPHONE() : + _savefile(NULL), _mixer(NULL), _timer(NULL), _offscreen(NULL), + _overlayVisible(false), _overlayBuffer(NULL), _fullscreen(NULL), + _mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0), + _secondaryTapped(false), _lastSecondaryTap(0) +{ + _queuedInputEvent.type = (Common::EventType)0; +} + +OSystem_IPHONE::~OSystem_IPHONE() { + delete _savefile; + delete _mixer; + delete _timer; + delete _offscreen; + delete _fullscreen; +} + +void OSystem_IPHONE::initBackend() { + _savefile = new DefaultSaveFileManager(); + _mixer = new Audio::Mixer(); + _timer = new DefaultTimerManager(); + + setSoundCallback(Audio::Mixer::mixCallback, _mixer); + + gettimeofday(&_startTime, NULL); + + OSystem::initBackend(); +} + +bool OSystem_IPHONE::hasFeature(Feature f) { + return false; +} + +void OSystem_IPHONE::setFeatureState(Feature f, bool enable) { +} + +bool OSystem_IPHONE::getFeatureState(Feature f) { + return false; +} + +const OSystem::GraphicsMode* OSystem_IPHONE::getSupportedGraphicsModes() const { + return s_supportedGraphicsModes; +} + + +int OSystem_IPHONE::getDefaultGraphicsMode() const { + return -1; +} + +bool OSystem_IPHONE::setGraphicsMode(const char *mode) { + return true; +} + +bool OSystem_IPHONE::setGraphicsMode(int mode) { + return true; +} + +int OSystem_IPHONE::getGraphicsMode() const { + return -1; +} + +void OSystem_IPHONE::initSize(uint width, uint height) { + //printf("initSize(%i, %i)\n", width, height); + + _screenWidth = width; + _screenHeight = height; + + if (_offscreen) + free(_offscreen); + + _offscreen = (byte *)malloc(width * height); + bzero(_offscreen, width * height); + + if (_overlayBuffer) + free(_overlayBuffer); + + int fullSize = _screenWidth * _screenHeight * sizeof(OverlayColor); + _overlayBuffer = (OverlayColor *)malloc(fullSize); + clearOverlay(); + + if (_fullscreen) { + free(_fullscreen); + } + _fullscreen = (uint16 *)malloc(fullSize); + bzero(_fullscreen, fullSize); + + iPhone_initSurface(height, width); + + _mouseVisible = false; +} + +int16 OSystem_IPHONE::getHeight() { + return _screenHeight; +} + +int16 OSystem_IPHONE::getWidth() { + return _screenWidth; +} + +void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint num) { + //printf("setPalette()\n"); + const byte *b = colors; + + for (uint i = start; i < num; ++i) { + _palette[i] = RGBToColor(b[0], b[1], b[2]); + b += 4; + } +} + +void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint num) { + //printf("grabPalette()\n"); +} + +void OSystem_IPHONE::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { + //printf("copyRectToScreen()\n"); + //Clip the coordinates + if (x < 0) { + w += x; + buf -= x; + x = 0; + } + + if (y < 0) { + h += y; + buf -= y * pitch; + y = 0; + } + + if (w > _screenWidth - x) { + w = _screenWidth - x; + } + + if (h > _screenHeight - y) { + h = _screenHeight - y; + } + + if (w <= 0 || h <= 0) + return; + + + byte *dst = _offscreen + y * _screenWidth + x; + if (_screenWidth == pitch && pitch == w) { + memcpy(dst, buf, h * w); + } else { + do { + memcpy(dst, buf, w); + buf += pitch; + dst += _screenWidth; + } while (--h); + } +} + +void OSystem_IPHONE::updateScreen() { + //printf("updateScreen()\n"); + + //uint16* screen = iPhone_getSurface(); + + int row; + if (_overlayVisible) { + for (int x = _screenWidth; x >= 1; x--) { + row = (_screenWidth - x) * _screenHeight; + for (int y = 0; y < _screenHeight; y++) { + _fullscreen[row + y] = _overlayBuffer[y * _screenWidth + x]; + } + } + } else { + for (int x = _screenWidth; x >= 1; x--) { + row = (_screenWidth - x) * _screenHeight; + for (int y = 0; y < _screenHeight; y++) { + _fullscreen[row + y] = _palette[_offscreen[y * _screenWidth + x]]; + } + } + } + + //draw mouse on top + if (_mouseVisible) { + for (uint x = _mouseWidth; x >= 1; x--) { + int mx = _mouseX + x; // + _mouseHotspotX; + row = (_screenWidth - mx) * _screenHeight; + if (mx >= 0 && mx < _screenWidth) { + for (uint y = 0; y < _mouseHeight; ++y) { + if (_mouseBuf[y * _mouseWidth + x] != _mouseKeyColour) { + int my = _mouseY + y; // + _mouseHotspotY; + + if ( my >= 0 && my < _screenHeight) + _fullscreen[row + my] = _palette[_mouseBuf[y * _mouseWidth + x]]; + } + } + } + } + } + + memcpy(iPhone_getSurface(), _fullscreen, (_screenWidth * _screenHeight) * 2); + iPhone_updateScreen(); +} + +Graphics::Surface *OSystem_IPHONE::lockScreen() { + //printf("lockScreen()\n"); + + _framebuffer.pixels = _offscreen; + _framebuffer.w = _screenWidth; + _framebuffer.h = _screenHeight; + _framebuffer.pitch = _screenWidth; + _framebuffer.bytesPerPixel = 1; + + return &_framebuffer; +} + +void OSystem_IPHONE::unlockScreen() { + //printf("unlockScreen()\n"); + updateScreen(); +} + +void OSystem_IPHONE::setShakePos(int shakeOffset) { +} + +void OSystem_IPHONE::showOverlay() { + //printf("showOverlay()\n"); + _overlayVisible = true; +} + +void OSystem_IPHONE::hideOverlay() { + //printf("hideOverlay()\n"); + _overlayVisible = false; +} + +void OSystem_IPHONE::clearOverlay() { + //printf("clearOverlay()\n"); + bzero(_overlayBuffer, _screenWidth * _screenHeight * sizeof(OverlayColor)); +} + +void OSystem_IPHONE::grabOverlay(OverlayColor *buf, int pitch) { + //printf("grabOverlay()\n"); + int h = _screenHeight; + OverlayColor *src = _overlayBuffer; + + do { + memcpy(buf, src, _screenWidth * sizeof(OverlayColor)); + src += _screenWidth; + buf += pitch; + } while (--h); +} + +void OSystem_IPHONE::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) { + //printf("copyRectToOverlay(buf, pitch=%i, x=%i, y=%i, w=%i, h=%i)\n", pitch, x, y, w, h); + + //Clip the coordinates + if (x < 0) { + w += x; + buf -= x; + x = 0; + } + + if (y < 0) { + h += y; + buf -= y * pitch; + y = 0; + } + + if (w > _screenWidth - x) { + w = _screenWidth - x; + } + + if (h > _screenHeight - y) { + h = _screenHeight - y; + } + + if (w <= 0 || h <= 0) + return; + + + OverlayColor *dst = _overlayBuffer + (y * _screenWidth + x); + if (_screenWidth == pitch && pitch == w) { + memcpy(dst, buf, h * w * sizeof(OverlayColor)); + } else { + do { + memcpy(dst, buf, w * sizeof(OverlayColor)); + buf += pitch; + dst += _screenWidth; + } while (--h); + } +} + +int16 OSystem_IPHONE::getOverlayHeight() { + return _screenHeight; +} + +int16 OSystem_IPHONE::getOverlayWidth() { + return _screenWidth; +} + +OverlayColor OSystem_IPHONE::RGBToColor(uint8 r, uint8 g, uint8 b) +{ + return (r & 0xF8) << 8 | (g & 0xFC) << 3 | (b >> 3); +} + +void OSystem_IPHONE::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) +{ + r = ((color & 0xF800) >> 11) << 3; + g = ((color & 0x07e0) >> 5) << 2; + b = (color & 0x001F) << 3; +} + +bool OSystem_IPHONE::showMouse(bool visible) { + bool last = _mouseVisible; + _mouseVisible = visible; + return last; +} + +void OSystem_IPHONE::warpMouse(int x, int y) { + //printf("warpMouse()\n"); + _mouseX = x; + _mouseY = y; +} + +void OSystem_IPHONE::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor, int cursorTargetScale) { + //printf("setMouseCursor()\n"); + + if (_mouseBuf != NULL && (_mouseWidth != w || _mouseHeight != h)) { + free(_mouseBuf); + _mouseBuf = NULL; + } + + if (_mouseBuf == NULL) { + _mouseBuf = (byte *)malloc(w * h); + } + + _mouseWidth = w; + _mouseHeight = h; + + _mouseHotspotX = hotspotX; + _mouseHotspotY = hotspotY; + + _mouseKeyColour = keycolor; + + memcpy(_mouseBuf, buf, w * h); +} + +bool OSystem_IPHONE::pollEvent(Common::Event &event) { + //printf("pollEvent()\n"); + + if (_queuedInputEvent.type != (Common::EventType)0) { + event = _queuedInputEvent; + _queuedInputEvent.type = (Common::EventType)0; + return true; + } + + int eventType; + float xUnit, yUnit; + + if (iPhone_fetchEvent(&eventType, &xUnit, &yUnit)) { + int x = (int)((1.0 - yUnit) * _screenWidth); + int y = (int)(xUnit * _screenHeight); + + long curTime = getMillis(); + + switch ((InputEvent)eventType) { + case kInputMouseDown: + //printf("Mouse down at (%u, %u)\n", x, y); + _lastMouseDown = curTime; + _mouseX = x; + _mouseY = y; + return false; + + break; + case kInputMouseUp: + //printf("Mouse up at (%u, %u)\n", x, y); + + if (curTime - _lastMouseDown < 250) { + event.type = Common::EVENT_LBUTTONDOWN; + event.mouse.x = _mouseX; + event.mouse.y = _mouseY; + + _queuedInputEvent.type = Common::EVENT_LBUTTONUP; + _queuedInputEvent.mouse.x = _mouseX; + _queuedInputEvent.mouse.y = _mouseY; + _lastMouseTap = curTime; + + // if (curTime - _lastMouseTap < 250 && !_overlayVisible) { + // 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 = 27; + // + // _lastMouseTap = 0; + // } else { + // + // } + } else { + return false; + } + + break; + case kInputMouseDragged: + //printf("Mouse dragged at (%u, %u)\n", x, y); + if (_secondaryTapped) { + int vecX = (x - _gestureStartX); + int vecY = (y - _gestureStartY); + int lengthSq = vecX * vecX + vecY * vecY; + //printf("Lengthsq: %u\n", lengthSq); + + if (lengthSq > 5000) { // Long enough gesture to react upon. + _gestureStartX = x; + _gestureStartY = y; + + float vecLength = sqrt(lengthSq); + float vecXNorm = vecX / vecLength; + float vecYNorm = vecY / vecLength; + + //printf("Swipe vector: (%.2f, %.2f)\n", vecXNorm, vecYNorm); + + if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm > 0.75) { + // Swipe down + 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_F5; + event.kbd.ascii = _queuedInputEvent.kbd.ascii = 27; + } else if (vecXNorm > -0.50 && vecXNorm < 0.50 && vecYNorm < -0.75) { + // Swipe up + 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_1; + event.kbd.ascii = _queuedInputEvent.kbd.ascii = 27; + } else if (vecXNorm > 0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) { + // Swipe right + return false; + } else if (vecXNorm < -0.75 && vecYNorm > -0.5 && vecYNorm < 0.5) { + // Swipe left + return false; + } else { + return false; + } + } else { + return false; + } + } else { + event.type = Common::EVENT_MOUSEMOVE; + event.mouse.x = x; + event.mouse.y = y; + _mouseX = x; + _mouseY = y; + } + break; + case kInputMouseSecondToggled: + _secondaryTapped = !_secondaryTapped; + //printf("Mouse second at (%u, %u). State now %s.\n", x, y, _secondaryTapped ? "on" : "off"); + if (_secondaryTapped) { + _lastSecondaryDown = curTime; + _gestureStartX = x; + _gestureStartY = y; + return false; + } else if (curTime - _lastSecondaryDown < 250 ) { + if (curTime - _lastSecondaryTap < 250 && !_overlayVisible) { + 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 = 27; + + _lastSecondaryTap = 0; + } else { + event.type = Common::EVENT_RBUTTONDOWN; + event.mouse.x = _mouseX; + event.mouse.y = _mouseY; + _queuedInputEvent.type = Common::EVENT_RBUTTONUP; + _queuedInputEvent.mouse.x = _mouseX; + _queuedInputEvent.mouse.y = _mouseY; + _lastSecondaryTap = curTime; + } + } else { + return false; + } + break; + default: + break; + } + + return true; + } + return false; +} + +uint32 OSystem_IPHONE::getMillis() { + //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)); +} + +void OSystem_IPHONE::delayMillis(uint msecs) { + //printf("delayMillis(%d)\n", msecs); + usleep(msecs * 1000); +} + +OSystem::MutexRef OSystem_IPHONE::createMutex(void) { + pthread_mutex_t *mutex = (pthread_mutex_t *) malloc(sizeof(pthread_mutex_t)); + pthread_mutex_init(mutex, NULL); + return (MutexRef)mutex; +} + +void OSystem_IPHONE::lockMutex(MutexRef mutex) { + pthread_mutex_lock((pthread_mutex_t *) mutex); +} + +void OSystem_IPHONE::unlockMutex(MutexRef mutex) { + pthread_mutex_unlock((pthread_mutex_t *) mutex); +} + +void OSystem_IPHONE::deleteMutex(MutexRef mutex) { + pthread_mutex_destroy((pthread_mutex_t *) mutex); + free(mutex); +} + +bool OSystem_IPHONE::setSoundCallback(SoundProc proc, void *param) { + return true; +} + +void OSystem_IPHONE::clearSoundCallback() { +} + +int OSystem_IPHONE::getOutputSampleRate() const { + return 22050; +} + +void OSystem_IPHONE::quit() { + //exit(0); +} + +void OSystem_IPHONE::setWindowCaption(const char *caption) { +} + +Common::SaveFileManager *OSystem_IPHONE::getSavefileManager() { + assert(_savefile); + return _savefile; +} + +Audio::Mixer *OSystem_IPHONE::getMixer() { + assert(_mixer); + return _mixer; +} + +Common::TimerManager *OSystem_IPHONE::getTimerManager() { + assert(_timer); + return _timer; +} + +OSystem *OSystem_IPHONE_create() { + return new OSystem_IPHONE(); +} + +void iphone_main(int argc, char *argv[]) { + 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! +} + +#endif diff --git a/backends/platform/iphone/osys_iphone.h b/backends/platform/iphone/osys_iphone.h new file mode 100644 index 0000000000..43d7897b6c --- /dev/null +++ b/backends/platform/iphone/osys_iphone.h @@ -0,0 +1,144 @@ +/* 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. + * + * $URL$ + * $Id$ + * + */ + +#ifdef IPHONE_BACKEND + +#include "graphics/surface.h" + +// #include <AudioToolbox/AudioQueue.h> +// +// /* Audio Resources */ +// #define AUDIO_BUFFERS 3 +// #define AUDIO_PRECACHE 4 +// #define WAVE_BUFFER_SIZE 735 +// #define WAVE_BUFFER_BANKS 25 +// +// typedef struct AQCallbackStruct { +// AudioQueueRef queue; +// UInt32 frameCount; +// AudioQueueBufferRef mBuffers[AUDIO_BUFFERS]; +// AudioStreamBasicDescription mDataFormat; +// } AQCallbackStruct; + +class OSystem_IPHONE : public OSystem { +protected: + static const OSystem::GraphicsMode s_supportedGraphicsModes[]; + + Common::SaveFileManager *_savefile; + Audio::Mixer *_mixer; + Common::TimerManager *_timer; + + Graphics::Surface _framebuffer; + byte *_offscreen; + OverlayColor *_overlayBuffer; + uint16 *_fullscreen; + + uint16 _palette[256]; + bool _overlayVisible; + uint16 _screenWidth; + uint16 _screenHeight; + + struct timeval _startTime; + + bool _mouseVisible; + byte *_mouseBuf; + byte _mouseKeyColour; + uint _mouseWidth, _mouseHeight; + int _mouseX, _mouseY; + int _mouseHotspotX, _mouseHotspotY; + long _lastMouseDown; + long _lastMouseTap; + Common::Event _queuedInputEvent; + bool _secondaryTapped; + long _lastSecondaryDown; + long _lastSecondaryTap; + int _gestureStartX, _gestureStartY; + +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; + bool setGraphicsMode(const char *name); + virtual bool setGraphicsMode(int mode); + virtual int getGraphicsMode() const; + virtual void initSize(uint width, uint height); + virtual int16 getHeight(); + virtual int16 getWidth(); + virtual void setPalette(const byte *colors, uint start, uint num); + virtual void grabPalette(byte *colors, uint start, uint num); + virtual void copyRectToScreen(const byte *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(OverlayColor *buf, int pitch); + virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h); + virtual int16 getOverlayHeight(); + virtual int16 getOverlayWidth(); + + virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b); + virtual void colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b); + + virtual bool showMouse(bool visible); + + virtual void warpMouse(int x, int y); + virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1); + + virtual bool pollEvent(Common::Event &event); + virtual uint32 getMillis(); + virtual void delayMillis(uint msecs); + + virtual MutexRef createMutex(void); + virtual void lockMutex(MutexRef mutex); + virtual void unlockMutex(MutexRef mutex); + virtual void deleteMutex(MutexRef mutex); + + typedef void (*SoundProc)(void *param, byte *buf, int len); + virtual bool setSoundCallback(SoundProc proc, void *param); + virtual void clearSoundCallback(); + virtual int getOutputSampleRate() const; + + virtual void quit(); + + virtual void setWindowCaption(const char *caption); + + virtual Common::SaveFileManager *getSavefileManager(); + virtual Audio::Mixer *getMixer(); + virtual Common::TimerManager *getTimerManager(); +}; + +#endif |