diff options
Diffstat (limited to 'backends')
| -rw-r--r-- | backends/keymapper/keymapper.cpp | 2 | ||||
| -rw-r--r-- | backends/midi/windows.cpp | 40 | ||||
| -rw-r--r-- | backends/platform/dc/dc.h | 2 | ||||
| -rw-r--r-- | backends/platform/iphone/iphone_common.h | 43 | ||||
| -rw-r--r-- | backends/platform/iphone/iphone_main.mm | 3 | ||||
| -rw-r--r-- | backends/platform/iphone/iphone_video.h | 26 | ||||
| -rw-r--r-- | backends/platform/iphone/iphone_video.mm | 564 | ||||
| -rw-r--r-- | backends/platform/iphone/osys_events.cpp | 50 | ||||
| -rw-r--r-- | backends/platform/iphone/osys_main.cpp | 21 | ||||
| -rw-r--r-- | backends/platform/iphone/osys_main.h | 36 | ||||
| -rw-r--r-- | backends/platform/iphone/osys_video.cpp | 432 | ||||
| -rw-r--r-- | backends/platform/iphone/osys_video.mm | 485 | ||||
| -rw-r--r-- | backends/platform/maemo/maemo-common.h | 9 | ||||
| -rw-r--r-- | backends/platform/maemo/maemo.cpp | 11 | 
14 files changed, 892 insertions, 832 deletions
diff --git a/backends/keymapper/keymapper.cpp b/backends/keymapper/keymapper.cpp index aafdd604a2..189f862469 100644 --- a/backends/keymapper/keymapper.cpp +++ b/backends/keymapper/keymapper.cpp @@ -119,7 +119,7 @@ void Keymapper::cleanupGameKeymaps() {  	// the game specific (=deleted) ones.  	Stack<MapRecord> newStack; -	for (int i = 0; i < _activeMaps.size(); i++) { +	for (Stack<MapRecord>::size_type i = 0; i < _activeMaps.size(); i++) {  		if (_activeMaps[i].global)  			newStack.push(_activeMaps[i]);  	} diff --git a/backends/midi/windows.cpp b/backends/midi/windows.cpp index 828411cd22..f4c5431d6e 100644 --- a/backends/midi/windows.cpp +++ b/backends/midi/windows.cpp @@ -177,13 +177,49 @@ MusicDevices WindowsMusicPlugin::getDevices() const {  	int numDevs = midiOutGetNumDevs();  	MIDIOUTCAPS tmp; +	Common::StringArray deviceNames;  	for (int i = 0; i < numDevs; i++) {  		if (midiOutGetDevCaps(i, &tmp, sizeof(MIDIOUTCAPS)) != MMSYSERR_NOERROR)  			break; +		deviceNames.push_back(tmp.szPname); +	} + +	// Check for non-unique device names. This may happen if someone has devices with identical +	// names (e. g. more than one USB device of the exact same hardware type). It seems that this +	// does happen in reality sometimes. We generate index numbers for these devices. +	// This is not an ideal solution, since this index could change whenever another USB +	// device gets plugged in or removed, switched off or just plugged into a different port. +	// Unfortunately midiOutGetDevCaps() does not generate any other unique information +	// that could be used. Our index numbers which match the device order should at least be +	// a little more stable than just using the midiOutGetDevCaps() device ID, since a missing +	// device (e.g. switched off) should actually not be harmful to our indices (as it would be +	// when using the device IDs). The cases where users have devices with identical names should +	// be rare enough anyway. +	Common::Array<int> nonUniqueIndex; +	for (int i = 0; i < numDevs; i++) { +		int match = -1; +		for (int ii = 0; ii < i; ii++) { +			if (deviceNames[i] == deviceNames[ii]) { +				if (nonUniqueIndex[ii] == -1) +					nonUniqueIndex[ii] = 0; +				if (++match == 0) +					++match; +			} +		} +		nonUniqueIndex.push_back(match); +	} + +	// We now add the index number to the non-unique device names to make them unique. +	for (int i = 0; i < numDevs; i++) { +		if (nonUniqueIndex[i] != -1) +			deviceNames[i] = Common::String::format("%s - #%.02d", deviceNames[i].c_str(), nonUniqueIndex[i]); +	} + +	for (Common::StringArray::iterator i = deviceNames.begin(); i != deviceNames.end(); ++i)  		// There is no way to detect the "MusicType" so I just set it to MT_GM  		// The user will have to manually select his MT32 type device and his GM type device. -		devices.push_back(MusicDevice(this, tmp.szPname, MT_GM)); -	} +		devices.push_back(MusicDevice(this, *i, MT_GM)); +  	return devices;  } diff --git a/backends/platform/dc/dc.h b/backends/platform/dc/dc.h index 2e32ff3eb4..8ca48bf19e 100644 --- a/backends/platform/dc/dc.h +++ b/backends/platform/dc/dc.h @@ -29,6 +29,8 @@  #include "backends/audiocd/default/default-audiocd.h"  #include "backends/fs/fs-factory.h"  #include "audio/mixer_intern.h" +#include "common/language.h" +#include "common/platform.h"  #ifdef DYNAMIC_MODULES  #include "backends/plugins/dynamic-plugin.h"  #endif diff --git a/backends/platform/iphone/iphone_common.h b/backends/platform/iphone/iphone_common.h index 5a46a6dde6..19e4f2ce9b 100644 --- a/backends/platform/iphone/iphone_common.h +++ b/backends/platform/iphone/iphone_common.h @@ -23,6 +23,8 @@  #ifndef BACKENDS_PLATFORM_IPHONE_IPHONE_COMMON_H  #define BACKENDS_PLATFORM_IPHONE_IPHONE_COMMON_H +#include "graphics/surface.h" +  enum InputEvent {  	kInputMouseDown,  	kInputMouseUp, @@ -55,21 +57,40 @@ enum GraphicsModes {  	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; +}; +  // On the ObjC side -void iPhone_setGraphicsMode(GraphicsModes mode); -void iPhone_updateScreen(int mouseX, int mouseY); -void iPhone_updateScreenRect(unsigned short *screen, int x1, int y1, int x2, int y2); -void iPhone_updateOverlayRect(unsigned short *screen, int x1, int y1, int x2, int y2); -void iPhone_initSurface(int width, int height); -void iPhone_setShakeOffset(int offset); +void iPhone_updateScreen();  bool iPhone_fetchEvent(int *outEvent, int *outX, int *outY);  const char *iPhone_getDocumentsDir();  bool iPhone_isHighResDevice(); -int iPhone_getScreenHeight(); -int iPhone_getScreenWidth(); -void iPhone_enableOverlay(int state); -void iPhone_showCursor(int state); -void iPhone_setMouseCursor(unsigned short *buffer, int width, int height, int hotspotX, int hotspotY);  uint getSizeNextPOT(uint size); diff --git a/backends/platform/iphone/iphone_main.mm b/backends/platform/iphone/iphone_main.mm index 1559ef8a6e..20406e6342 100644 --- a/backends/platform/iphone/iphone_main.mm +++ b/backends/platform/iphone/iphone_main.mm @@ -20,6 +20,9 @@   *   */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL +  #include <UIKit/UIKit.h>  #include <Foundation/NSThread.h> diff --git a/backends/platform/iphone/iphone_video.h b/backends/platform/iphone/iphone_video.h index 43a643ab4a..55a4acb7c7 100644 --- a/backends/platform/iphone/iphone_video.h +++ b/backends/platform/iphone/iphone_video.h @@ -32,9 +32,11 @@  #include <OpenGLES/ES1/glext.h>  #include "iphone_keyboard.h" +#include "iphone_common.h"  @interface iPhoneView : UIView { -	void *_screenSurface; +	VideoContext _videoContext; +  	NSMutableArray *_events;  	SoftKeyboard *_keyboardView; @@ -47,19 +49,33 @@  	UIDeviceOrientation _orientation; +	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;  }  - (id)initWithFrame:(struct CGRect)frame; -- (void)drawRect:(CGRect)frame; +- (VideoContext *)getVideoContext; -- (void *)getSurface; +- (void)drawRect:(CGRect)frame; +- (void)createScreenTexture;  - (void)initSurface;  - (void)setViewTransformation; @@ -71,6 +87,8 @@  - (void)updateMouseSurface;  - (void)clearColorBuffer; +- (void)notifyMouseMove; +- (void)updateMouseCursorScaling;  - (void)updateMouseCursor;  - (id)getEvent; @@ -83,4 +101,6 @@  @end +extern iPhoneView *g_iPhoneViewInstance; +  #endif diff --git a/backends/platform/iphone/iphone_video.mm b/backends/platform/iphone/iphone_video.mm index 86365cbefe..04aaf59b21 100644 --- a/backends/platform/iphone/iphone_video.mm +++ b/backends/platform/iphone/iphone_video.mm @@ -20,49 +20,22 @@   *   */ +// Disable symbol overrides so that we can use system headers. +#define FORBIDDEN_SYMBOL_ALLOW_ALL +  #include "iphone_video.h" -#include "iphone_common.h" -static iPhoneView *sharedInstance = nil; -static GraphicsModes _graphicsMode = kGraphicsModeLinear; -static int _width = 0; -static int _height = 0; +#include "graphics/colormasks.h" + +iPhoneView *g_iPhoneViewInstance = nil;  static int _fullWidth;  static int _fullHeight; -static CGRect _gameScreenRect; - -static char *_gameScreenTextureBuffer = 0; -static int _gameScreenTextureWidth = 0; -static int _gameScreenTextureHeight = 0; - -static char *_overlayTexBuffer = 0; -static int _overlayTexWidth = 0; -static int _overlayTexHeight = 0; -static int _overlayWidth = 0; -static int _overlayHeight = 0; -static CGRect _overlayRect;  static int _needsScreenUpdate = 0; -static int _overlayIsEnabled = 0;  static UITouch *_firstTouch = NULL;  static UITouch *_secondTouch = NULL; -static unsigned short *_mouseCursor = NULL; -static int _mouseCursorHeight = 0; -static int _mouseCursorWidth = 0; -static int _mouseCursorHotspotX = 0; -static int _mouseCursorHotspotY = 0; -static int _mouseX = 0; -static int _mouseY = 0; -static int _mouseCursorEnabled = 0; - -static GLint _renderBufferWidth; -static GLint _renderBufferHeight; - -static int _shakeOffsetY; -static int _scaledShakeOffsetY; -  #if 0  static long lastTick = 0;  static int frames = 0; @@ -83,83 +56,20 @@ int printOglError(const char *file, int line) {  	return retCode;  } -void iPhone_setGraphicsMode(GraphicsModes mode) { -	_graphicsMode = mode; - -	[sharedInstance performSelectorOnMainThread:@selector(setGraphicsMode) withObject:nil waitUntilDone: YES]; -} - -void iPhone_showCursor(int state) { -	_mouseCursorEnabled = state; -} - -void iPhone_setMouseCursor(unsigned short *buffer, int width, int height, int hotspotX, int hotspotY) { -	_mouseCursor = buffer; - -	_mouseCursorWidth = width; -	_mouseCursorHeight = height; - -	_mouseCursorHotspotX = hotspotX; -	_mouseCursorHotspotY = hotspotY; - -	[sharedInstance performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES]; -} - -void iPhone_enableOverlay(int state) { -	_overlayIsEnabled = state; - -	[sharedInstance performSelectorOnMainThread:@selector(clearColorBuffer) withObject:nil waitUntilDone: YES]; -} - -int iPhone_getScreenHeight() { -	return _overlayHeight; -} - -int iPhone_getScreenWidth() { -	return _overlayWidth; -} -  bool iPhone_isHighResDevice() {  	return _fullHeight > 480;  } -void iPhone_updateScreen(int mouseX, int mouseY) { +void iPhone_updateScreen() {  	//printf("Mouse: (%i, %i)\n", mouseX, mouseY); - -	_mouseX = mouseX; -	_mouseY = mouseY; -  	if (!_needsScreenUpdate) {  		_needsScreenUpdate = 1; -		[sharedInstance performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO]; +		[g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateSurface) withObject:nil waitUntilDone: NO];  	}  } -void iPhone_updateScreenRect(unsigned short *screen, int x1, int y1, int x2, int y2) { -	for (int y = y1; y < y2; ++y) -		memcpy(&_gameScreenTextureBuffer[(y * _gameScreenTextureWidth + x1) * 2], &screen[y * _width + x1], (x2 - x1) * 2); -} - -void iPhone_updateOverlayRect(unsigned short *screen, int x1, int y1, int x2, int y2) { -	//printf("Overlaywidth: %u, fullwidth %u\n", _overlayWidth, _fullWidth); -	for (int y = y1; y < y2; ++y) -		memcpy(&_overlayTexBuffer[(y * _overlayTexWidth + x1) * 2], &screen[y * _overlayWidth + x1], (x2 - x1) * 2); -} - -void iPhone_initSurface(int width, int height) { -	_width = width; -	_height = height; -	_shakeOffsetY = 0; -	[sharedInstance performSelectorOnMainThread:@selector(initSurface) withObject:nil waitUntilDone: YES]; -} - -void iPhone_setShakeOffset(int offset) { -	_shakeOffsetY = offset; -	[sharedInstance performSelectorOnMainThread:@selector(setViewTransformation) withObject:nil waitUntilDone: YES]; -} -  bool iPhone_fetchEvent(int *outEvent, int *outX, int *outY) { -	id event = [sharedInstance getEvent]; +	id event = [g_iPhoneViewInstance getEvent];  	if (event == nil) {  		return false;  	} @@ -196,92 +106,16 @@ const char *iPhone_getDocumentsDir() {  	return [documentsDirectory UTF8String];  } -/** - * Converts portrait mode coordinates into rotated mode coordinates. - */ -static bool convertToRotatedCoords(UIDeviceOrientation orientation, CGPoint point, 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; -	} -} - -static bool getMouseCoords(UIDeviceOrientation orientation, CGPoint point, int *x, int *y) { -	if (!convertToRotatedCoords(orientation, point, &point)) -		return false; - -	CGRect *area; -	int width, height, offsetY; -	if (_overlayIsEnabled) { -		area = &_overlayRect; -		width = _overlayWidth; -		height = _overlayHeight; -		offsetY = _shakeOffsetY; -	} else { -		area = &_gameScreenRect; -		width = _width; -		height = _height; -		offsetY = _scaledShakeOffsetY; -	} - -	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); - -	// Clip coordinates -	if (*x < 0 || *x > CGRectGetWidth(*area) || *y < 0 || *y > CGRectGetHeight(*area)) -			return false; - -	return true; -} - -static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) { -	if (!tex) -		return; - -	glBindTexture(GL_TEXTURE_2D, tex); printOpenGLError(); - -	GLint filter = GL_LINEAR; - -	switch (mode) { -	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(); -} -  @implementation iPhoneView  + (Class)layerClass {  	return [CAEAGLLayer class];  } +- (VideoContext *)getVideoContext { +	return &_videoContext; +} +  - (void)createContext {  	CAEAGLLayer *eaglLayer = (CAEAGLLayer *)self.layer; @@ -317,20 +151,18 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  			return;  		} -		_overlayHeight = _renderBufferWidth; -		_overlayWidth = _renderBufferHeight; -		_overlayTexWidth = getSizeNextPOT(_overlayHeight); -		_overlayTexHeight = getSizeNextPOT(_overlayWidth); +		_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  		// and just use it later on. -		_overlayTexCoords[2] = _overlayTexCoords[6] = _overlayWidth / (GLfloat)_overlayTexWidth; -		_overlayTexCoords[5] = _overlayTexCoords[7] = _overlayHeight / (GLfloat)_overlayTexHeight; +		_overlayTexCoords[2] = _overlayTexCoords[6] = _videoContext.overlayWidth / (GLfloat)overlayTextureWidth; +		_overlayTexCoords[5] = _overlayTexCoords[7] = _videoContext.overlayHeight / (GLfloat)overlayTextureHeight; -		int textureSize = _overlayTexWidth * _overlayTexHeight * 2; -		_overlayTexBuffer = (char *)malloc(textureSize); -		memset(_overlayTexBuffer, 0, textureSize); +		_videoContext.overlayTexture.create(overlayTextureWidth, overlayTextureHeight, Graphics::createPixelFormat<5551>());  		glViewport(0, 0, _renderBufferWidth, _renderBufferHeight); printOpenGLError();  		glClearColor(0.0f, 0.0f, 0.0f, 1.0f); printOpenGLError(); @@ -356,13 +188,15 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	_fullWidth = (int)frame.size.width;  	_fullHeight = (int)frame.size.height; -	sharedInstance = self; +	g_iPhoneViewInstance = self;  	_keyboardView = nil;  	_screenTexture = 0;  	_overlayTexture = 0;  	_mouseCursorTexture = 0; +	_scaledShakeOffsetY = 0; +  	_gameScreenVertCoords[0] = _gameScreenVertCoords[1] =  	    _gameScreenVertCoords[2] = _gameScreenVertCoords[3] =  	    _gameScreenVertCoords[4] = _gameScreenVertCoords[5] = @@ -383,6 +217,16 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	    _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]; @@ -396,12 +240,9 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  		[_keyboardView dealloc];  	} -	free(_gameScreenTextureBuffer); -	free(_overlayTexBuffer); -} - -- (void *)getSurface { -	return _screenSurface; +	_videoContext.screenTexture.free(); +	_videoContext.overlayTexture.free(); +	_videoContext.mouseTexture.free();  }  - (void)drawRect:(CGRect)frame { @@ -419,10 +260,32 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  #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(); +} +  - (void)setGraphicsMode { -	setFilterModeForTexture(_screenTexture, _graphicsMode); -	setFilterModeForTexture(_overlayTexture, _graphicsMode); -	setFilterModeForTexture(_mouseCursorTexture, _graphicsMode); +	[self setFilterModeForTexture:_screenTexture]; +	[self setFilterModeForTexture:_overlayTexture]; +	[self setFilterModeForTexture:_mouseCursorTexture];  }  - (void)updateSurface { @@ -435,10 +298,10 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	[self updateMainSurface]; -	if (_overlayIsEnabled) +	if (_videoContext.overlayVisible)  		[self updateOverlaySurface]; -	if (_mouseCursorEnabled) +	if (_videoContext.mouseIsVisible)  		[self updateMouseSurface];  	glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); @@ -446,17 +309,70 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  } +- (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(); -		setFilterModeForTexture(_mouseCursorTexture, _graphicsMode); +		[self setFilterModeForTexture:_mouseCursorTexture];  	} -	glBindTexture(GL_TEXTURE_2D, _mouseCursorTexture); printOpenGLError(); -	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getSizeNextPOT(_mouseCursorWidth), getSizeNextPOT(_mouseCursorHeight), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _mouseCursor); printOpenGLError(); +	[self updateMouseCursorScaling]; -	free(_mouseCursor); -	_mouseCursor = NULL; +	_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.pixels); printOpenGLError();  }  - (void)updateMainSurface { @@ -468,7 +384,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	// 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, _gameScreenTextureWidth, _gameScreenTextureHeight, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _gameScreenTextureBuffer); printOpenGLError(); +	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _videoContext.screenTexture.w, _videoContext.screenTexture.h, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, _videoContext.screenTexture.pixels); printOpenGLError();  	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();  } @@ -477,147 +393,83 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	glTexCoordPointer(2, GL_FLOAT, 0, _overlayTexCoords); printOpenGLError();  	glBindTexture(GL_TEXTURE_2D, _overlayTexture); printOpenGLError(); -	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _overlayTexWidth, _overlayTexHeight, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, _overlayTexBuffer); 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.pixels); printOpenGLError();  	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); printOpenGLError();  }  - (void)updateMouseSurface { -	int width = _mouseCursorWidth; -	int height = _mouseCursorHeight; - -	int mouseX = _mouseX; -	int mouseY = _mouseY; - -	int hotspotX = _mouseCursorHotspotX; -	int hotspotY = _mouseCursorHotspotY; - -	CGRect *rect; -	int maxWidth, maxHeight; - -	if (!_overlayIsEnabled) { -		rect = &_gameScreenRect; -		maxWidth = _width; -		maxHeight = _height; -	} else { -		rect = &_overlayRect; -		maxWidth = _overlayWidth; -		maxHeight = _overlayHeight; -	} - -	const GLfloat scaleX = CGRectGetWidth(*rect) / (GLfloat)maxWidth; -	const GLfloat scaleY = CGRectGetHeight(*rect) / (GLfloat)maxHeight; - -	mouseX = (int)(mouseX * scaleX); -	mouseY = (int)(mouseY * scaleY); -	hotspotX = (int)(hotspotX * scaleX); -	hotspotY = (int)(hotspotY * scaleY); -	width = (int)(width * scaleX); -	height = (int)(height * scaleY); - -	mouseX -= hotspotX; -	mouseY -= hotspotY; - -	mouseX += (int)CGRectGetMinX(*rect); -	mouseY += (int)CGRectGetMinY(*rect); - -	GLfloat vertices[] = { -		// Top left -		mouseX        , mouseY, -		// Top right -		mouseX + width, mouseY, -		// Bottom left -		mouseX        , mouseY + height, -		// Bottom right -		mouseX + width, mouseY + height -	}; - -	//printf("Cursor: width %u height %u\n", _mouseCursorWidth, _mouseCursorHeight); - -	float texWidth = _mouseCursorWidth / (float)getSizeNextPOT(_mouseCursorWidth); -	float texHeight = _mouseCursorHeight / (float)getSizeNextPOT(_mouseCursorHeight); - -	const GLfloat texCoords[] = { -		// Top left -		0       , 0, -		// Top right -		texWidth, 0, -		// Bottom left -		0       , texHeight, -		// Bottom right -		texWidth, texHeight -	}; - -	glVertexPointer(2, GL_FLOAT, 0, vertices); printOpenGLError(); -	glTexCoordPointer(2, GL_FLOAT, 0, texCoords); printOpenGLError(); +	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)initSurface { -	_gameScreenTextureWidth = getSizeNextPOT(_width); -	_gameScreenTextureHeight = getSizeNextPOT(_height); - -	_gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _width / (GLfloat)_gameScreenTextureWidth; -	_gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _height / (GLfloat)_gameScreenTextureHeight; +- (void)setUpOrientation:(UIDeviceOrientation)orientation width:(int *)width height:(int *)height { +	_orientation = orientation; -	_orientation = [[UIDevice currentDevice] orientation]; +	glMatrixMode(GL_PROJECTION); +	glLoadIdentity(); +	// We always force the origin (0,0) to be in the upper left corner.  	switch (_orientation) { -	case UIDeviceOrientationLandscapeLeft:  	case UIDeviceOrientationLandscapeRight: -	case UIDeviceOrientationPortrait: +		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; -	} - -	//printf("Window: (%d, %d), Surface: (%d, %d), Texture(%d, %d)\n", _fullWidth, _fullHeight, _width, _height, _gameScreenTextureWidth, _gameScreenTextureHeight); -	glMatrixMode(GL_PROJECTION); -	glLoadIdentity(); +		glOrthof(0, _renderBufferWidth, _renderBufferHeight, 0, 0, 1); printOpenGLError(); -	int screenWidth, screenHeight; +		*width = _renderBufferWidth; +		*height = _renderBufferHeight; +		break; +	} +} -	// Set the origin (0,0) depending on the rotation mode. -	if (_orientation ==  UIDeviceOrientationLandscapeRight) { -		glRotatef( 90, 0, 0, 1); printOpenGLError(); -		glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError(); +- (void)createScreenTexture { +	const uint screenTexWidth = getSizeNextPOT(_videoContext.screenWidth); +	const uint screenTexHeight = getSizeNextPOT(_videoContext.screenHeight); -		screenWidth = _renderBufferHeight; -		screenHeight = _renderBufferWidth; -	} else if (_orientation == UIDeviceOrientationLandscapeLeft) { -		glRotatef(-90, 0, 0, 1); printOpenGLError(); -		glOrthof(0, _renderBufferHeight, _renderBufferWidth, 0, 0, 1); printOpenGLError(); +	_gameScreenTexCoords[2] = _gameScreenTexCoords[6] = _videoContext.screenWidth / (GLfloat)screenTexWidth; +	_gameScreenTexCoords[5] = _gameScreenTexCoords[7] = _videoContext.screenHeight / (GLfloat)screenTexHeight; -		screenWidth = _renderBufferHeight; -		screenHeight = _renderBufferWidth; -	} else if (_orientation == UIDeviceOrientationPortrait) { -		glOrthof(0, _renderBufferWidth, _renderBufferHeight, 0, 0, 1); printOpenGLError(); +	_videoContext.screenTexture.create(screenTexWidth, screenTexHeight, Graphics::createPixelFormat<565>()); +} -		screenWidth = _renderBufferWidth; -		screenHeight = _renderBufferHeight; -	} +- (void)initSurface { +	int screenWidth, screenHeight; +	[self setUpOrientation:[[UIDevice currentDevice] orientation] width:&screenWidth height:&screenHeight];  	if (_screenTexture > 0) {  		glDeleteTextures(1, &_screenTexture); printOpenGLError();  	}  	glGenTextures(1, &_screenTexture); printOpenGLError(); -	setFilterModeForTexture(_screenTexture, _graphicsMode); +	[self setFilterModeForTexture:_screenTexture];  	if (_overlayTexture > 0) {  		glDeleteTextures(1, &_overlayTexture); printOpenGLError();  	}  	glGenTextures(1, &_overlayTexture); printOpenGLError(); -	setFilterModeForTexture(_overlayTexture, _graphicsMode); - -	free(_gameScreenTextureBuffer); -	int textureSize = _gameScreenTextureWidth * _gameScreenTextureHeight * 2; -	_gameScreenTextureBuffer = (char *)malloc(textureSize); -	memset(_gameScreenTextureBuffer, 0, textureSize); +	[self setFilterModeForTexture:_overlayTexture];  	glBindRenderbufferOES(GL_RENDERBUFFER_OES, _viewRenderbuffer); printOpenGLError(); @@ -628,10 +480,19 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  		[[_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 (_orientation == UIDeviceOrientationLandscapeLeft || _orientation ==  UIDeviceOrientationLandscapeRight) { -		GLfloat gameScreenRatio = (GLfloat)_width / (GLfloat)_height; +		GLfloat gameScreenRatio = adjustedWidth / adjustedHeight;  		GLfloat screenRatio = (GLfloat)screenWidth / (GLfloat)screenHeight;  		// These are the width/height according to the portrait layout! @@ -660,7 +521,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  		_gameScreenRect = CGRectMake(xOffset, yOffset, rectWidth, rectHeight);  		overlayPortraitRatio = 1.0f;  	} else { -		float ratio = (float)_height / (float)_width; +		GLfloat ratio = adjustedHeight / adjustedWidth;  		int height = (int)(screenWidth * ratio);  		//printf("Making rect (%u, %u)\n", screenWidth, height);  		_gameScreenRect = CGRectMake(0, 0, screenWidth, height); @@ -674,7 +535,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  		[self addSubview:[_keyboardView inputView]];  		[self addSubview: _keyboardView];  		[[_keyboardView inputView] becomeFirstResponder]; -		overlayPortraitRatio = (_overlayHeight * ratio) / _overlayWidth; +		overlayPortraitRatio = (_videoContext.overlayHeight * ratio) / _videoContext.overlayWidth;  	}  	_overlayRect = CGRectMake(0, 0, screenWidth, screenHeight * overlayPortraitRatio); @@ -688,6 +549,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	_overlayVertCoords[5] = _overlayVertCoords[7] = CGRectGetMaxY(_overlayRect);  	[self setViewTransformation]; +	[self updateMouseCursorScaling];  }  - (void)setViewTransformation { @@ -698,7 +560,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	// 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)(_shakeOffsetY / (GLfloat)_height * CGRectGetHeight(_overlayRect)); +	_scaledShakeOffsetY = (int)(_videoContext.shakeOffsetY / (GLfloat)_videoContext.screenHeight * CGRectGetHeight(_overlayRect));  	// Apply the shakeing to the output screen.  	glTranslatef(0, -_scaledShakeOffsetY, 0); @@ -732,6 +594,64 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	[_events addObject: event];  } +/** + * 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 { +	if (![self convertToRotatedCoords:point result:&point]) +		return false; + +	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); + +	// Clip coordinates +	if (*x < 0 || *x > width || *y < 0 || *y > height) +		return false; + +	return true; +} +  - (void)deviceOrientationChanged:(UIDeviceOrientation)orientation {  	switch (orientation) {  	case UIDeviceOrientationLandscapeLeft: @@ -762,7 +682,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	case 1: {  		UITouch *touch = [touches anyObject];  		CGPoint point = [touch locationInView:self]; -		if (!getMouseCoords(_orientation, point, &x, &y)) +		if (![self getMouseCoords:point eventX:&x eventY:&y])  			return;  		_firstTouch = touch; @@ -780,7 +700,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	case 2: {  		UITouch *touch = [touches anyObject];  		CGPoint point = [touch locationInView:self]; -		if (!getMouseCoords(_orientation, point, &x, &y)) +		if (![self getMouseCoords:point eventX:&x eventY:&y])  			return;  		_secondTouch = touch; @@ -804,7 +724,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	for (UITouch *touch in touches) {  		if (touch == _firstTouch) {  			CGPoint point = [touch locationInView:self]; -			if (!getMouseCoords(_orientation, point, &x, &y)) +			if (![self getMouseCoords:point eventX:&x eventY:&y])  				return;  			[self addEvent: @@ -817,7 +737,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  			 ];  		} else if (touch == _secondTouch) {  			CGPoint point = [touch locationInView:self]; -			if (!getMouseCoords(_orientation, point, &x, &y)) +			if (![self getMouseCoords:point eventX:&x eventY:&y])  				return;  			[self addEvent: @@ -840,7 +760,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	case 1: {  		UITouch *touch = [[allTouches allObjects] objectAtIndex:0];  		CGPoint point = [touch locationInView:self]; -		if (!getMouseCoords(_orientation, point, &x, &y)) +		if (![self getMouseCoords:point eventX:&x eventY:&y])  			return;  		[self addEvent: @@ -857,7 +777,7 @@ static void setFilterModeForTexture(GLuint tex, GraphicsModes mode) {  	case 2: {  		UITouch *touch = [[allTouches allObjects] objectAtIndex:1];  		CGPoint point = [touch locationInView:self]; -		if (!getMouseCoords(_orientation, point, &x, &y)) +		if (![self getMouseCoords:point eventX:&x eventY:&y])  			return;  		[self addEvent: diff --git a/backends/platform/iphone/osys_events.cpp b/backends/platform/iphone/osys_events.cpp index c167da35e6..85efbda208 100644 --- a/backends/platform/iphone/osys_events.cpp +++ b/backends/platform/iphone/osys_events.cpp @@ -122,8 +122,8 @@ bool OSystem_IPHONE::handleEvent_mouseDown(Common::Event &event, int x, int y) {  	if (_mouseClickAndDragEnabled) {  		event.type = Common::EVENT_LBUTTONDOWN; -		event.mouse.x = _mouseX; -		event.mouse.y = _mouseY; +		event.mouse.x = _videoContext->mouseX; +		event.mouse.y = _videoContext->mouseY;  		return true;  	} else {  		_lastMouseDown = getMillis(); @@ -140,17 +140,17 @@ bool OSystem_IPHONE::handleEvent_mouseUp(Common::Event &event, int x, int y) {  			return false;  	} else if (_mouseClickAndDragEnabled) {  		event.type = Common::EVENT_LBUTTONUP; -		event.mouse.x = _mouseX; -		event.mouse.y = _mouseY; +		event.mouse.x = _videoContext->mouseX; +		event.mouse.y = _videoContext->mouseY;  	} else {  		if (getMillis() - _lastMouseDown < 250) {  			event.type = Common::EVENT_LBUTTONDOWN; -			event.mouse.x = _mouseX; -			event.mouse.y = _mouseY; +			event.mouse.x = _videoContext->mouseX; +			event.mouse.y = _videoContext->mouseY;  			_queuedInputEvent.type = Common::EVENT_LBUTTONUP; -			_queuedInputEvent.mouse.x = _mouseX; -			_queuedInputEvent.mouse.y = _mouseY; +			_queuedInputEvent.mouse.x = _videoContext->mouseX; +			_queuedInputEvent.mouse.y = _videoContext->mouseY;  			_lastMouseTap = getMillis();  			_queuedEventTime = _lastMouseTap + kQueuedInputEventDelay;  		} else @@ -167,12 +167,12 @@ bool OSystem_IPHONE::handleEvent_secondMouseDown(Common::Event &event, int x, in  	if (_mouseClickAndDragEnabled) {  		event.type = Common::EVENT_LBUTTONUP; -		event.mouse.x = _mouseX; -		event.mouse.y = _mouseY; +		event.mouse.x = _videoContext->mouseX; +		event.mouse.y = _videoContext->mouseY;  		_queuedInputEvent.type = Common::EVENT_RBUTTONDOWN; -		_queuedInputEvent.mouse.x = _mouseX; -		_queuedInputEvent.mouse.y = _mouseY; +		_queuedInputEvent.mouse.x = _videoContext->mouseX; +		_queuedInputEvent.mouse.y = _videoContext->mouseY;  	} else  		return false; @@ -184,7 +184,7 @@ bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int  	if (curTime - _lastSecondaryDown < 400) {  		//printf("Right tap!\n"); -		if (curTime - _lastSecondaryTap < 400 && !_overlayVisible) { +		if (curTime - _lastSecondaryTap < 400 && !_videoContext->overlayVisible) {  			//printf("Right escape!\n");  			event.type = Common::EVENT_KEYDOWN;  			_queuedInputEvent.type = Common::EVENT_KEYUP; @@ -197,11 +197,11 @@ bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int  		} else if (!_mouseClickAndDragEnabled) {  			//printf("Rightclick!\n");  			event.type = Common::EVENT_RBUTTONDOWN; -			event.mouse.x = _mouseX; -			event.mouse.y = _mouseY; +			event.mouse.x = _videoContext->mouseX; +			event.mouse.y = _videoContext->mouseY;  			_queuedInputEvent.type = Common::EVENT_RBUTTONUP; -			_queuedInputEvent.mouse.x = _mouseX; -			_queuedInputEvent.mouse.y = _mouseY; +			_queuedInputEvent.mouse.x = _videoContext->mouseX; +			_queuedInputEvent.mouse.y = _videoContext->mouseY;  			_lastSecondaryTap = curTime;  			_queuedEventTime = curTime + kQueuedInputEventDelay;  		} else { @@ -211,8 +211,8 @@ bool OSystem_IPHONE::handleEvent_secondMouseUp(Common::Event &event, int x, int  	}  	if (_mouseClickAndDragEnabled) {  		event.type = Common::EVENT_RBUTTONUP; -		event.mouse.x = _mouseX; -		event.mouse.y = _mouseY; +		event.mouse.x = _videoContext->mouseX; +		event.mouse.y = _videoContext->mouseY;  	}  	return true; @@ -234,11 +234,11 @@ bool OSystem_IPHONE::handleEvent_mouseDragged(Common::Event &event, int x, int y  		_lastPadX = x;  		_lastPadY = y; -		mouseNewPosX = (int)(_mouseX - deltaX / 0.5f); -		mouseNewPosY = (int)(_mouseY - deltaY / 0.5f); +		mouseNewPosX = (int)(_videoContext->mouseX - deltaX / 0.5f); +		mouseNewPosY = (int)(_videoContext->mouseY - deltaY / 0.5f); -		int widthCap = _overlayVisible ? _overlayWidth : _screenWidth; -		int heightCap = _overlayVisible ? _overlayHeight : _screenHeight; +		int widthCap = _videoContext->overlayVisible ? _videoContext->overlayWidth : _videoContext->screenWidth; +		int heightCap = _videoContext->overlayVisible ? _videoContext->overlayHeight : _videoContext->screenHeight;  		if (mouseNewPosX < 0)  			mouseNewPosX = 0; @@ -350,10 +350,10 @@ void  OSystem_IPHONE::handleEvent_orientationChanged(int orientation) {  	if (_screenOrientation != newOrientation) {  		_screenOrientation = newOrientation; -		iPhone_initSurface(_screenWidth, _screenHeight); +		updateOutputSurface();  		dirtyFullScreen(); -		if (_overlayVisible) +		if (_videoContext->overlayVisible)  			dirtyFullOverlayScreen();  		updateScreen();  	} diff --git a/backends/platform/iphone/osys_main.cpp b/backends/platform/iphone/osys_main.cpp index 2bdc09c9ce..f3e0d97b97 100644 --- a/backends/platform/iphone/osys_main.cpp +++ b/backends/platform/iphone/osys_main.cpp @@ -55,26 +55,28 @@ SoundProc OSystem_IPHONE::s_soundCallback = NULL;  void *OSystem_IPHONE::s_soundParam = NULL;  OSystem_IPHONE::OSystem_IPHONE() : -	_mixer(NULL), _gameScreenRaw(NULL), -	_overlayVisible(false), _gameScreenConverted(NULL), -	_mouseHeight(0), _mouseWidth(0), _mouseBuf(NULL), _lastMouseTap(0), _queuedEventTime(0), +	_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), -	_overlayHeight(0), _overlayWidth(0), _overlayBuffer(0), _mouseCursorPaletteEnabled(false), -	_currentGraphicsMode(kGraphicsModeLinear) { +	_mouseCursorPaletteEnabled(false) {  	_queuedInputEvent.type = Common::EVENT_INVALID;  	_touchpadModeEnabled = !iPhone_isHighResDevice();  	_fsFactory = new POSIXFilesystemFactory(); +	initVideoContext();  }  OSystem_IPHONE::~OSystem_IPHONE() {  	AudioQueueDispose(s_AudioQueue.queue, true);  	delete _mixer; -	free(_gameScreenRaw); -	free(_gameScreenConverted); +	// 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. +	if (_framebuffer.pixels == _videoContext->screenTexture.pixels) +		_framebuffer.free(); +	_mouseBuffer.free();  }  int OSystem_IPHONE::timerHandler(int t) { @@ -120,6 +122,9 @@ void OSystem_IPHONE::setFeatureState(Feature f, bool enable) {  			_mouseCursorPaletteEnabled = enable;  		}  		break; +	case kFeatureAspectRatioCorrection: +		_videoContext->asprectRatioCorrection = enable; +		break;  	default:  		break; @@ -130,6 +135,8 @@ bool OSystem_IPHONE::getFeatureState(Feature f) {  	switch (f) {  	case kFeatureCursorPalette:  		return _mouseCursorPaletteEnabled; +	case kFeatureAspectRatioCorrection: +		return _videoContext->asprectRatioCorrection;  	default:  		return false; diff --git a/backends/platform/iphone/osys_main.h b/backends/platform/iphone/osys_main.h index e4b3d358d5..5d0f60c34c 100644 --- a/backends/platform/iphone/osys_main.h +++ b/backends/platform/iphone/osys_main.h @@ -59,39 +59,27 @@ protected:  	static SoundProc s_soundCallback;  	static void *s_soundParam; -	int _currentGraphicsMode; -  	Audio::MixerImpl *_mixer; -	Graphics::Surface _framebuffer; -	byte *_gameScreenRaw; -	OverlayColor  *_overlayBuffer; -	uint16 _overlayHeight; -	uint16 _overlayWidth; +	VideoContext *_videoContext; -	uint16 *_gameScreenConverted; +	Graphics::Surface _framebuffer;  	// For use with the game texture  	uint16  _gamePalette[256];  	// For use with the mouse texture  	uint16  _gamePaletteRGBA5551[256]; -	bool _overlayVisible; -	uint16 _screenWidth; -	uint16 _screenHeight;  	struct timeval _startTime;  	uint32 _timeSuspended; -	bool _mouseVisible;  	bool _mouseCursorPaletteEnabled;  	uint16 _mouseCursorPalette[256]; -	byte *_mouseBuf; -	byte _mouseKeyColor; -	uint _mouseWidth, _mouseHeight; -	uint _mouseX, _mouseY; -	int _mouseHotspotX, _mouseHotspotY; +	Graphics::Surface _mouseBuffer; +	uint16 _mouseKeyColor;  	bool _mouseDirty;  	bool _mouseNeedTextureUpdate; +  	long _lastMouseDown;  	long _lastMouseTap;  	long _queuedEventTime; @@ -133,9 +121,18 @@ public:  	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(); +#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 @@ -192,13 +189,14 @@ public:  	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 drawDirtyOverlayRect(const Common::Rect &dirtyRect); -	void updateHardwareSurfaceForRect(const Common::Rect &updatedRect);  	void updateMouseTexture();  	static void AQBufferCallback(void *in, AudioQueueRef inQ, AudioQueueBufferRef outQB);  	static int timerHandler(int t); diff --git a/backends/platform/iphone/osys_video.cpp b/backends/platform/iphone/osys_video.cpp deleted file mode 100644 index e26c360c82..0000000000 --- a/backends/platform/iphone/osys_video.cpp +++ /dev/null @@ -1,432 +0,0 @@ -/* 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" - -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: -		_currentGraphicsMode = mode; -		iPhone_setGraphicsMode((GraphicsModes)mode); -		return true; - -	default: -		return false; -	} -} - -int OSystem_IPHONE::getGraphicsMode() const { -	return _currentGraphicsMode; -} - -void OSystem_IPHONE::initSize(uint width, uint height, const Graphics::PixelFormat *format) { -	//printf("initSize(%i, %i)\n", width, height); - -	_screenWidth = width; -	_screenHeight = height; - -	free(_gameScreenRaw); - -	_gameScreenRaw = (byte *)malloc(width * height); -	bzero(_gameScreenRaw, width * height); - -	//free(_overlayBuffer); - -	int fullSize = _screenWidth * _screenHeight * sizeof(OverlayColor); -	//_overlayBuffer = (OverlayColor *)malloc(fullSize); -	clearOverlay(); - -	free(_gameScreenConverted); - -	_gameScreenConverted = (uint16 *)malloc(fullSize); -	bzero(_gameScreenConverted, fullSize); - -	iPhone_initSurface(width, height); - -	if (_overlayBuffer == NULL) { -		_overlayHeight = iPhone_getScreenHeight(); -		_overlayWidth = iPhone_getScreenWidth(); - -		printf("Overlay: (%u x %u)\n", _overlayWidth, _overlayHeight); -		_overlayBuffer = new OverlayColor[_overlayHeight * _overlayWidth]; -	} - -	_fullScreenIsDirty = false; -	dirtyFullScreen(); -	_mouseVisible = false; -	_mouseCursorPaletteEnabled = false; -	_screenChangeCount++; -	updateScreen(); -} - -int16 OSystem_IPHONE::getHeight() { -	return _screenHeight; -} - -int16 OSystem_IPHONE::getWidth() { -	return _screenWidth; -} - -void OSystem_IPHONE::setPalette(const byte *colors, uint start, uint 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(); -} - -void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint 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 byte *buf, int pitch, int x, int y, int w, int h) { -	//printf("copyRectToScreen(%i, %i, %i, %i)\n", 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; - -	if (!_fullScreenIsDirty) { -		_dirtyRects.push_back(Common::Rect(x, y, x + w, y + h)); -	} - - -	byte *dst = _gameScreenRaw + 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(): %i dirty rects.\n", _dirtyRects.size()); - -	if (_dirtyRects.size() == 0 && _dirtyOverlayRects.size() == 0 && !_mouseDirty) -		return; - -	internUpdateScreen(); -	_mouseDirty = false; -	_fullScreenIsDirty = false; -	_fullScreenOverlayIsDirty = false; - -	iPhone_updateScreen(_mouseX, _mouseY); -} - -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); -		updateHardwareSurfaceForRect(dirtyRect); -	} - -	if (_overlayVisible) { -		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) { -	int h = dirtyRect.bottom - dirtyRect.top; -	int w = dirtyRect.right - dirtyRect.left; - -	byte  *src = &_gameScreenRaw[dirtyRect.top * _screenWidth + dirtyRect.left]; -	uint16 *dst = &_gameScreenConverted[dirtyRect.top * _screenWidth + dirtyRect.left]; -	for (int y = h; y > 0; y--) { -		for (int x = w; x > 0; x--) -			*dst++ = _gamePalette[*src++]; - -		dst += _screenWidth - w; -		src += _screenWidth - w; -	} -} - -void OSystem_IPHONE::drawDirtyOverlayRect(const Common::Rect &dirtyRect) { -	iPhone_updateOverlayRect(_overlayBuffer, dirtyRect.left, dirtyRect.top, dirtyRect.right, dirtyRect.bottom); -} - -void OSystem_IPHONE::updateHardwareSurfaceForRect(const Common::Rect &updatedRect) { -	iPhone_updateScreenRect(_gameScreenConverted, updatedRect.left, updatedRect.top, updatedRect.right, updatedRect.bottom); -} - -Graphics::Surface *OSystem_IPHONE::lockScreen() { -	//printf("lockScreen()\n"); - -	_framebuffer.pixels = _gameScreenRaw; -	_framebuffer.w = _screenWidth; -	_framebuffer.h = _screenHeight; -	_framebuffer.pitch = _screenWidth; -	_framebuffer.format = Graphics::PixelFormat::createFormatCLUT8(); - -	return &_framebuffer; -} - -void OSystem_IPHONE::unlockScreen() { -	//printf("unlockScreen()\n"); -	dirtyFullScreen(); -} - -void OSystem_IPHONE::setShakePos(int shakeOffset) { -	//printf("setShakePos(%i)\n", shakeOffset); -	iPhone_setShakeOffset(shakeOffset); -	// HACK: We use this to force a redraw. -	_mouseDirty = true; -} - -void OSystem_IPHONE::showOverlay() { -	//printf("showOverlay()\n"); -	_overlayVisible = true; -	dirtyFullOverlayScreen(); -	updateScreen(); -	iPhone_enableOverlay(true); -} - -void OSystem_IPHONE::hideOverlay() { -	//printf("hideOverlay()\n"); -	_overlayVisible = false; -	_dirtyOverlayRects.clear(); -	dirtyFullScreen(); -	iPhone_enableOverlay(false); -} - -void OSystem_IPHONE::clearOverlay() { -	//printf("clearOverlay()\n"); -	bzero(_overlayBuffer, _overlayWidth * _overlayHeight * sizeof(OverlayColor)); -	dirtyFullOverlayScreen(); -} - -void OSystem_IPHONE::grabOverlay(OverlayColor *buf, int pitch) { -	//printf("grabOverlay()\n"); -	int h = _overlayHeight; -	OverlayColor *src = _overlayBuffer; - -	do { -		memcpy(buf, src, _overlayWidth * sizeof(OverlayColor)); -		src += _overlayWidth; -		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 > _overlayWidth - x) -		w = _overlayWidth - x; - -	if (h > _overlayHeight - y) -		h = _overlayHeight - y; - -	if (w <= 0 || h <= 0) -		return; - -	if (!_fullScreenOverlayIsDirty) { -		_dirtyOverlayRects.push_back(Common::Rect(x, y, x + w, y + h)); -	} - -	OverlayColor *dst = _overlayBuffer + (y * _overlayWidth + x); -	if (_overlayWidth == pitch && pitch == w) -		memcpy(dst, buf, h * w * sizeof(OverlayColor)); -	else { -		do { -			memcpy(dst, buf, w * sizeof(OverlayColor)); -			buf += pitch; -			dst += _overlayWidth; -		} while (--h); -	} -} - -int16 OSystem_IPHONE::getOverlayHeight() { -	return _overlayHeight; -} - -int16 OSystem_IPHONE::getOverlayWidth() { -	return _overlayWidth; -} - -bool OSystem_IPHONE::showMouse(bool visible) { -	bool last = _mouseVisible; -	_mouseVisible = visible; -	iPhone_showCursor(visible); -	_mouseDirty = true; - -	return last; -} - -void OSystem_IPHONE::warpMouse(int x, int y) { -	//printf("warpMouse()\n"); - -	_mouseX = x; -	_mouseY = y; -	_mouseDirty = true; -} - -void OSystem_IPHONE::dirtyFullScreen() { -	if (!_fullScreenIsDirty) { -		_dirtyRects.clear(); -		_dirtyRects.push_back(Common::Rect(0, 0, _screenWidth, _screenHeight)); -		_fullScreenIsDirty = true; -	} -} - -void OSystem_IPHONE::dirtyFullOverlayScreen() { -	if (!_fullScreenOverlayIsDirty) { -		_dirtyOverlayRects.clear(); -		_dirtyOverlayRects.push_back(Common::Rect(0, 0, _overlayWidth, _overlayHeight)); -		_fullScreenOverlayIsDirty = true; -	} -} - -void OSystem_IPHONE::setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { -	//printf("setMouseCursor(%i, %i, scale %u)\n", hotspotX, hotspotY, cursorTargetScale); - -	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; - -	_mouseKeyColor = (byte)keycolor; - -	memcpy(_mouseBuf, buf, w * h); - -	_mouseDirty = true; -	_mouseNeedTextureUpdate = true; -} - -void OSystem_IPHONE::setCursorPalette(const byte *colors, uint start, uint 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() { -	int texWidth = getSizeNextPOT(_mouseWidth); -	int texHeight = getSizeNextPOT(_mouseHeight); -	int bufferSize = texWidth * texHeight * sizeof(int16); -	uint16 *mouseBuf = (uint16 *)malloc(bufferSize); -	memset(mouseBuf, 0, bufferSize); - -	const uint16 *palette; -	if (_mouseCursorPaletteEnabled) -		palette = _mouseCursorPalette; -	else -		palette = _gamePaletteRGBA5551; - -	for (uint x = 0; x < _mouseWidth; ++x) { -		for (uint y = 0; y < _mouseHeight; ++y) { -			const byte color = _mouseBuf[y * _mouseWidth + x]; -			if (color != _mouseKeyColor) -				mouseBuf[y * texWidth + x] = palette[color] | 0x1; -			else -				mouseBuf[y * texWidth + x] = 0x0; -		} -	} - -	iPhone_setMouseCursor(mouseBuf, _mouseWidth, _mouseHeight, _mouseHotspotX, _mouseHotspotY); -} diff --git a/backends/platform/iphone/osys_video.mm b/backends/platform/iphone/osys_video.mm new file mode 100644 index 0000000000..2b5e78bd35 --- /dev/null +++ b/backends/platform/iphone/osys_video.mm @@ -0,0 +1,485 @@ +/* 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.pixels == _videoContext->screenTexture.pixels) +		_framebuffer.pixels = 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]; + +	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 +		assert(_videoContext->screenTexture.format == *format); +		// 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() { +} + +OSystem::TransactionError OSystem_IPHONE::endGFXTransaction() { +	_screenChangeCount++; +	updateOutputSurface(); +	[g_iPhoneViewInstance performSelectorOnMainThread:@selector(setGraphicsMode) withObject:nil waitUntilDone: YES]; + +	// TODO: Can we return better error codes? +	return kTransactionSuccess; +} + +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) { +	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(); +} + +void OSystem_IPHONE::grabPalette(byte *colors, uint start, uint 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 byte *buf, int pitch, int x, int y, int w, int h) { +	//printf("copyRectToScreen(%i, %i, %i, %i)\n", 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 > (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, buf, h * pitch); +	} else { +		do { +			memcpy(dst, buf, w * _framebuffer.format.bytesPerPixel); +			buf += pitch; +			dst += _framebuffer.pitch; +		} while (--h); +	} +} + +void OSystem_IPHONE::updateScreen() { +	//printf("updateScreen(): %i dirty rects.\n", _dirtyRects.size()); + +	if (_dirtyRects.size() == 0 && _dirtyOverlayRects.size() == 0 && !_mouseDirty) +		return; + +	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.getBasePtr(0, 0), _videoContext->overlayTexture.h * _videoContext->overlayTexture.pitch); +	dirtyFullOverlayScreen(); +} + +void OSystem_IPHONE::grabOverlay(OverlayColor *buf, int pitch) { +	//printf("grabOverlay()\n"); +	int h = _videoContext->overlayHeight; + +	const byte *src = (const byte *)_videoContext->overlayTexture.getBasePtr(0, 0); +	do { +		memcpy(buf, src, _videoContext->overlayWidth * sizeof(OverlayColor)); +		src += _videoContext->overlayTexture.pitch; +		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 > (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, buf, w * sizeof(OverlayColor)); +		buf += 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) { +	bool last = _videoContext->mouseIsVisible; +	_videoContext->mouseIsVisible = visible; +	_mouseDirty = true; + +	return last; +} + +void OSystem_IPHONE::warpMouse(int x, int y) { +	//printf("warpMouse()\n"); +	_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 byte *buf, uint w, uint h, int hotspotX, int hotspotY, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) { +	//printf("setMouseCursor(%i, %i, scale %u)\n", hotspotX, hotspotY, cursorTargetScale); + +	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.pixels) +		_mouseBuffer.create(w, h, pixelFormat); + +	_videoContext->mouseWidth = w; +	_videoContext->mouseHeight = h; + +	_videoContext->mouseHotspotX = hotspotX; +	_videoContext->mouseHotspotY = hotspotY; + +	_mouseKeyColor = keycolor; + +	memcpy(_mouseBuffer.getBasePtr(0, 0), buf, h * _mouseBuffer.pitch); + +	_mouseDirty = true; +	_mouseNeedTextureUpdate = true; +} + +void OSystem_IPHONE::setCursorPalette(const byte *colors, uint start, uint 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.getBasePtr(0, 0); +		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.getBasePtr(0, 0), (const byte *)_mouseBuffer.getBasePtr(0, 0), 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.getBasePtr(0, 0); +				uint8 *dstRaw = (uint8 *)mouseTexture.getBasePtr(0, 0); + +				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.getBasePtr(0, 0), 0, mouseTexture.h * mouseTexture.pitch); +		} +	} + +	[g_iPhoneViewInstance performSelectorOnMainThread:@selector(updateMouseCursor) withObject:nil waitUntilDone: YES]; +} diff --git a/backends/platform/maemo/maemo-common.h b/backends/platform/maemo/maemo-common.h index 453c70c45f..0442b9c0ae 100644 --- a/backends/platform/maemo/maemo-common.h +++ b/backends/platform/maemo/maemo-common.h @@ -43,15 +43,6 @@ struct Model {  	bool hasMenuKey;  }; -static const Model models[] = { -	{"SU-18", kModelType770, "770", false, true}, -	{"RX-34", kModelTypeN800, "N800", false, true}, -	{"RX-44", kModelTypeN810, "N810", true, true}, -	{"RX-48", kModelTypeN810, "N810W", true, true}, -	{"RX-51", kModelTypeN900, "N900", true, false}, -	{0, kModelTypeInvalid, 0, true, true} -}; -  enum CustomEventType {  	kEventClickMode = 1,  	kEventInvalid = 0 diff --git a/backends/platform/maemo/maemo.cpp b/backends/platform/maemo/maemo.cpp index 209e527e3f..a127926eb0 100644 --- a/backends/platform/maemo/maemo.cpp +++ b/backends/platform/maemo/maemo.cpp @@ -156,10 +156,19 @@ void OSystem_SDL_Maemo::setWindowCaption(const char *caption) {  	setXWindowName(cap.c_str());  } +static const Model models[] = { +	{"SU-18", kModelType770, "770", false, true}, +	{"RX-34", kModelTypeN800, "N800", false, true}, +	{"RX-44", kModelTypeN810, "N810", true, true}, +	{"RX-48", kModelTypeN810, "N810W", true, true}, +	{"RX-51", kModelTypeN900, "N900", true, false}, +	{0, kModelTypeInvalid, 0, true, true} +}; +  const Maemo::Model OSystem_SDL_Maemo::detectModel() {  	Common::String deviceHwId = Common::String(getenv("SCUMMVM_MAEMO_DEVICE"));  	const Model *model; -	for (model = models; model->hwId; model++) { +	for (model = models; model->hwId; ++model) {  		if (deviceHwId.equals(model->hwId))  			return *model;  	}  | 
