All pastes #1293326 Raw Edit

scummvm.ipod.diff

public diff v1 · immutable
#1293326 ·published 2008-12-25 04:32 UTC
rendered paste body
Index: configure===================================================================--- configure	(revision 35535)+++ configure	(working copy)@@ -585,7 +585,7 @@  Configuration:   -h, --help             display this help and exit-  --backend=BACKEND      backend to build (sdl, morphos, dc, gp2x, iphone, null) [sdl]+  --backend=BACKEND      backend to build (sdl, morphos, dc, gp2x, iphone, ipod, null) [sdl]  Installation directories:   --prefix=DIR           use this prefix for installing ScummVM [/usr/local]@@ -813,6 +813,10 @@ 	_host_os=iphone 	_host_cpu=arm 	;;+ipod)+        _host_os=uclinux-elf+        _host_cpu=arm+        ;; neuros) 	_host_os=linux 	_host_cpu=arm@@ -1186,6 +1190,18 @@ 			_backend="iphone" 			_build_hq_scalers="no" 			;;+                ipod)+                        echo "Cross-compiling to $_host, forcing endianness, alignment and type sizes"+                        DEFINES="$DEFINES -DUNIX -D_BSD_SOURCE -DIPOD -DDISABLE_HELP"+                        LDFLAGS="$LDFLAGS -Wl,-elf2flt"+                        _endian=little+                        _need_memalign=yes+                        type_1_byte='char'+                        type_2_byte='short'+                        type_4_byte='int'+                        _backend="ipod"+                        _build_hq_scalers="no"+                        ;; 		*) 			echo "Continuing with auto-detected values ... if you have problems, please add your target to configure." 			;;@@ -1724,6 +1740,11 @@ 		DEFINES="$DEFINES -DIPHONE_BACKEND" 		MODULES="$MODULES backends/platform/iphone" 		;;+        ipod)+                INCLUDES="$INCLUDES -I../libs/ttk/sdlincludes"+                LIBS="$LIBS ../libs/ttk/libs/SDL/libSDL.a"+                MODULES="$MODULES backends/platform/ipod"+                ;; 	*) 		echo "support for $_backend backend not implemented in configure script yet" 		exit 1Index: gui/themes/scummmodern.zip===================================================================Cannot display: file marked as a binary type.svn:mime-type = application/octet-streamIndex: common/str.cpp===================================================================--- common/str.cpp	(revision 35535)+++ common/str.cpp	(working copy)@@ -35,7 +35,7 @@  namespace Common { -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) const String String::emptyString; #else const char *String::emptyString = "";Index: common/config-manager.h===================================================================--- common/config-manager.h	(revision 35535)+++ common/config-manager.h	(working copy)@@ -68,7 +68,7 @@  	typedef HashMap<String, Domain, IgnoreCase_Hash, IgnoreCase_EqualTo> DomainMap; -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	/** The name of the application domain (normally 'scummvm'). */ 	static const String kApplicationDomain; Index: common/config-manager.cpp===================================================================--- common/config-manager.cpp	(revision 35535)+++ common/config-manager.cpp	(working copy)@@ -40,7 +40,7 @@  namespace Common { -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD))  const String ConfigManager::kApplicationDomain("scummvm"); const String ConfigManager::kTransientDomain("__TRANSIENT");@@ -396,7 +396,7 @@  	if (!domain->contains(key)) { #if 1-#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	return String::emptyString; #else 	return ConfMan._emptyString;@@ -603,7 +603,7 @@ 	if (iter != end()) 		return iter->_value; -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	return String::emptyString; #else 	return ConfMan._emptyString;Index: common/str.h===================================================================--- common/str.h	(revision 35535)+++ common/str.h	(working copy)@@ -90,7 +90,7 @@ 	}  public:-#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	static const String emptyString; #else 	static const char *emptyString;Index: engines/scumm/scumm.cpp===================================================================--- engines/scumm/scumm.cpp	(revision 35535)+++ engines/scumm/scumm.cpp	(working copy)@@ -68,7 +68,7 @@  #include "sound/mixer.h" -#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) namespace Graphics { 	extern void initfonts(); }@@ -533,9 +533,12 @@ 		_herculesBuf = (byte *)malloc(Common::kHercW * Common::kHercH); 	} +#ifndef IPOD+// This breaks on the ipod; for some reason the gDebugLevels list has _anchor._next = _anchor._prev = NULL. I have absolutely no idea why. 	// Add debug levels 	for (int i = 0; i < ARRAYSIZE(debugChannels); ++i) 		Common::addSpecialDebugLevel(debugChannels[i].flag,  debugChannels[i].channel, debugChannels[i].desc);+#endif	  	syst->getEventManager()->registerRandomSource(_rnd, "scumm"); }@@ -1185,7 +1188,7 @@  	_res->setHeapThreshold(400000, maxHeapThreshold); -#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	Graphics::initfonts(); #endif Index: graphics/fonts/newfont.cpp===================================================================--- graphics/fonts/newfont.cpp	(revision 35535)+++ graphics/fonts/newfont.cpp	(working copy)@@ -7435,7 +7435,7 @@ 	sizeof(_font_bits)/sizeof(bitmap_t) }; -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) extern const NewFont g_sysfont(desc); #else DEFINE_FONT(g_sysfont)Index: graphics/fonts/newfont_big.cpp===================================================================--- graphics/fonts/newfont_big.cpp	(revision 35535)+++ graphics/fonts/newfont_big.cpp	(working copy)@@ -5539,7 +5539,7 @@ 	sizeof(_font_bits)/sizeof(bitmap_t) }; -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) extern const NewFont g_sysfont_big(desc); #else DEFINE_FONT(g_sysfont_big)Index: graphics/fonts/consolefont.cpp===================================================================--- graphics/fonts/consolefont.cpp	(revision 35535)+++ graphics/fonts/consolefont.cpp	(working copy)@@ -5651,7 +5651,7 @@ 	sizeof(_font_bits)/sizeof(bitmap_t) }; -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) extern const NewFont g_consolefont(desc); #else DEFINE_FONT(g_consolefont)Index: graphics/font.h===================================================================--- graphics/font.h	(revision 35535)+++ graphics/font.h	(working copy)@@ -139,7 +139,7 @@ 	static NewFont *loadFromCache(Common::SeekableReadStream &stream); }; -#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if (defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) #	define DEFINE_FONT(n) \ 		const NewFont *n;	\ 		void create_##n() {	\Index: graphics/fontman.cpp===================================================================--- graphics/fontman.cpp	(revision 35535)+++ graphics/fontman.cpp	(working copy)@@ -29,7 +29,7 @@  namespace Graphics { -#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) const ScummFont g_scummfont; extern const NewFont g_sysfont; extern const NewFont g_sysfont_big;@@ -69,7 +69,7 @@  const Font *FontManager::getFontByUsage(FontUsage usage) const { 	switch (usage) {-#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))+#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD)) 	case kOSDFont: 		return &g_scummfont; 	case kConsoleFont:Index: tools/convbdf.c===================================================================--- tools/convbdf.c	(revision 35535)+++ tools/convbdf.c	(working copy)@@ -930,7 +930,7 @@ 			bbuf, 			pf->defaultchar); -	fprintf(ofp, "\n" "#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__))\n");+	fprintf(ofp, "\n" "#if !(defined(PALMOS_ARM) || defined(PALMOS_DEBUG) || defined(__GP32__) || defined(IPOD))\n"); 	fprintf(ofp, "extern const NewFont g_sysfont(desc);\n"); 	fprintf(ofp, "#else\n"); 	fprintf(ofp, "DEFINE_FONT(g_sysfont)\n");Index: backends/platform/ipod/graphics.cpp===================================================================--- backends/platform/ipod/graphics.cpp	(revision 0)+++ backends/platform/ipod/graphics.cpp	(revision 0)@@ -0,0 +1,1579 @@+/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/graphics.cpp $+ * $Id: graphics.cpp 35443 2008-12-19 17:54:45Z eriktorbjorn $+ *+ */++#include "backends/platform/ipod/sdl.h"+#include "common/util.h"+#include "graphics/font.h"+#include "graphics/fontman.h"+#include "graphics/scaler.h"+#include "graphics/surface.h"++static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {+	{"1x", "No scaling", GFX_NORMAL},+	{"0.5x", "Half size", GFX_HALF},+	{0, 0, 0}+};++// Scaler function which scales by 0.5+void Scaleo5x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) {+      dstPitch >>= 1; srcPitch >>= 1;+      const int tgtHeight = height >> 1;+      const int tgtWidth = width >> 1;+      uint16 dstColor;+      for(int i=0;i<tgtHeight; i++) {+              uint16 *srcRow = (uint16*)srcPtr + (i << 1)*srcPitch;+              uint16 *srcRow2 = (uint16*)srcPtr + ((i << 1)+1)*srcPitch;+              uint16 *dstRow = (uint16*)dstPtr + i*dstPitch;+              for(int j=0;j<tgtWidth; j++) {+                      int srcx = j << 1;+                      dstColor = (*(srcRow + srcx) & 0xE79C) >> 2;+                      dstColor += (*(srcRow + srcx+1) & 0xE79C) >> 2;+                      dstColor += (*(srcRow2 + srcx) & 0xE79C) >> 2;+                      dstColor += (*(srcRow + srcx+1) & 0xE79C) >> 2;+                      *(dstRow + j) = dstColor;+              }+      }+}++const OSystem::GraphicsMode *OSystem_IPOD::getSupportedGraphicsModes() const {+	return s_supportedGraphicsModes;+}++int OSystem_IPOD::getDefaultGraphicsMode() const {+        SDL_Rect **rs = SDL_ListModes(0, SDL_SWSURFACE);+        if(rs == (SDL_Rect **)-1) {+		return GFX_NORMAL;+        } else {+               if((*rs)->w < 320 || (*rs)->h < 240) {+			return GFX_HALF;+               }+        }+	return GFX_NORMAL;+}++void OSystem_IPOD::beginGFXTransaction(void) {+	assert(_transactionMode == kTransactionNone);++	_transactionMode = kTransactionActive;++	_transactionDetails.sizeChanged = false;++	_transactionDetails.needHotswap = false;+	_transactionDetails.needUpdatescreen = false;++	_transactionDetails.normal1xScaler = false;++	_oldVideoMode = _videoMode;+}++OSystem::TransactionError OSystem_IPOD::endGFXTransaction(void) {+	int errors = kTransactionSuccess;++	assert(_transactionMode != kTransactionNone);++	if (_transactionMode == kTransactionRollback) {+		if (_videoMode.fullscreen != _oldVideoMode.fullscreen) {+			errors |= kTransactionFullscreenFailed;++			_videoMode.fullscreen = _oldVideoMode.fullscreen;+		} else if (_videoMode.aspectRatio != _oldVideoMode.aspectRatio) {+			errors |= kTransactionAspectRatioFailed;++			_videoMode.aspectRatio = _oldVideoMode.aspectRatio;+		} else if (_videoMode.mode != _oldVideoMode.mode) {+			errors |= kTransactionModeSwitchFailed;++			_videoMode.mode = _oldVideoMode.mode;+			_videoMode.scaleFactor = _oldVideoMode.scaleFactor;+		} else if (_videoMode.screenWidth != _oldVideoMode.screenWidth || _videoMode.screenHeight != _oldVideoMode.screenHeight) {+			errors |= kTransactionSizeChangeFailed;++			_videoMode.screenWidth = _oldVideoMode.screenWidth;+			_videoMode.screenHeight = _oldVideoMode.screenHeight;+			_videoMode.overlayWidth = _oldVideoMode.overlayWidth;+			_videoMode.overlayHeight = _oldVideoMode.overlayHeight;+		}++		if (_videoMode.fullscreen == _oldVideoMode.fullscreen &&+			_videoMode.aspectRatio == _oldVideoMode.aspectRatio &&+			_videoMode.mode == _oldVideoMode.mode &&+			_videoMode.screenWidth == _oldVideoMode.screenWidth &&+		   	_videoMode.screenHeight == _oldVideoMode.screenHeight) {++			// Our new video mode would now be exactly the same as the+			// old one. Since we still can not assume SDL_SetVideoMode+			// to be working fine, we need to invalidate the old video+			// mode, so loadGFXMode would error out properly.+			_oldVideoMode.setup = false;+		}+	}++	if (_transactionDetails.sizeChanged) {+		unloadGFXMode();+		if (!loadGFXMode()) {+			if (_oldVideoMode.setup) {+				_transactionMode = kTransactionRollback;+				errors |= endGFXTransaction();+			}+		} else {+			setGraphicsModeIntern();+			clearOverlay();++			_videoMode.setup = true;+			_modeChanged = true;+		}+	} else if (_transactionDetails.needHotswap) {+		setGraphicsModeIntern();+		if (!hotswapGFXMode()) {+			if (_oldVideoMode.setup) {+				_transactionMode = kTransactionRollback;+				errors |= endGFXTransaction();+			}+		} else {+			_videoMode.setup = true;+			_modeChanged = true;++			if (_transactionDetails.needUpdatescreen)+				internUpdateScreen();+		}+	} else if (_transactionDetails.needUpdatescreen) {+		setGraphicsModeIntern();+		internUpdateScreen();+	}++	_transactionMode = kTransactionNone;+	return (TransactionError)errors;+}++bool OSystem_IPOD::setGraphicsMode(int mode) {+	Common::StackLock lock(_graphicsMutex);++	assert(_transactionMode == kTransactionActive);++	if (_oldVideoMode.setup && _oldVideoMode.mode == mode)+		return true;++	double newScaleFactor = 1.0;++	switch(mode) {+	case GFX_NORMAL:+		newScaleFactor = 1.0;+		break;+	case GFX_HALF:+		newScaleFactor = 0.5;+		break;+	default:+		warning("unknown gfx mode %d", mode);+		return false;+	}++	_transactionDetails.normal1xScaler = (mode == GFX_NORMAL);+	if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor)+		_transactionDetails.needHotswap = true;++	_transactionDetails.needUpdatescreen = true;++	_videoMode.mode = mode;+	_videoMode.scaleFactor = newScaleFactor;++	return true;+}++void OSystem_IPOD::setGraphicsModeIntern() {+	Common::StackLock lock(_graphicsMutex);+	ScalerProc *newScalerProc = 0;++	switch (_videoMode.mode) {+	case GFX_NORMAL:+		newScalerProc = Normal1x;+		break;+	case GFX_HALF:+		newScalerProc = Scaleo5x;+		break;+	default:+		error("Unknown gfx mode %d", _videoMode.mode);+	}++	_scalerProc = newScalerProc;++	if (!_screen || !_hwscreen)+		return;++	// Blit everything to the screen+	_forceFull = true;++	// Even if the old and new scale factors are the same, we may have a+	// different scaler for the cursor now.+	blitCursor();+}++int OSystem_IPOD::getGraphicsMode() const {+	assert (_transactionMode == kTransactionNone);+	return _videoMode.mode;+}++void OSystem_IPOD::initSize(uint w, uint h) {+	assert(_transactionMode == kTransactionActive);++	// Avoid redundant res changes+	if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)+		return;++	_videoMode.screenWidth = w;+	_videoMode.screenHeight = h;++	_cksumNum = (w * h / (8 * 8));++	_transactionDetails.sizeChanged = true;++	free(_dirtyChecksums);+	_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));+}++bool OSystem_IPOD::loadGFXMode() {+	assert(_inited);+	_forceFull = true;++	int hwW, hwH;++	_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;+	_videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;++	if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)+		_videoMode.aspectRatio = false;++	if (_videoMode.aspectRatio)+		_videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);++	hwW = _videoMode.screenWidth * _videoMode.scaleFactor;+	hwH = effectiveScreenHeight();++	//+	// Create the surface that contains the 8 bit game data+	//+	_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight, 8, 0, 0, 0, 0);+	if (_screen == NULL)+		error("allocating _screen failed");++	//+	// Create the surface that contains the scaled graphics in 16 bit mode+	// For iPods, you don't get a choice on your size, so just take the only thing SDL_ListModes gives you.+	//++	SDL_Rect **rs = SDL_ListModes(0, SDL_SWSURFACE);+	if(rs == (SDL_Rect**)-1) {+	      _hwscreen = SDL_SetVideoMode(hwW, hwH, 16,+		      _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE+	      );+	} else {+	      _hwscreen = SDL_SetVideoMode((*rs)->w, (*rs)->h, 16,+		      _videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE+	      );+	      _hwScreenOffsetX = ((*rs)->w - hwW) >> 1;+	      _hwScreenOffsetY = ((*rs)->h - hwH) >> 1;+	      +	      SDL_Rect clippingRect = {_hwScreenOffsetX, _hwScreenOffsetY, hwW, hwH};+	      SDL_SetClipRect(_hwscreen, &clippingRect);+	}++	if (_hwscreen == NULL) {+		// DON'T use error(), as this tries to bring up the debug+		// console, which WON'T WORK now that _hwscreen is hosed.++		if (!_oldVideoMode.setup) {+			warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());+			quit();+		} else {+			return false;+		}+	}++	//+	// Create the surface used for the graphics in 16 bit before scaling, and also the overlay+	//++	// Distinguish 555 and 565 mode+	if (_hwscreen->format->Rmask == 0x7C00)+		InitScalers(555);+	else+		InitScalers(565);++	// Need some extra bytes around when using 2xSaI+	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);++	if (_tmpscreen == NULL)+		error("allocating _tmpscreen failed");++	_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);++	if (_overlayscreen == NULL)+		error("allocating _overlayscreen failed");++	_overlayFormat.bytesPerPixel = _overlayscreen->format->BytesPerPixel;++	_overlayFormat.rLoss = _overlayscreen->format->Rloss;+	_overlayFormat.gLoss = _overlayscreen->format->Gloss;+	_overlayFormat.bLoss = _overlayscreen->format->Bloss;+	_overlayFormat.aLoss = _overlayscreen->format->Aloss;++	_overlayFormat.rShift = _overlayscreen->format->Rshift;+	_overlayFormat.gShift = _overlayscreen->format->Gshift;+	_overlayFormat.bShift = _overlayscreen->format->Bshift;+	_overlayFormat.aShift = _overlayscreen->format->Ashift;++	_tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);++	if (_tmpscreen2 == NULL)+		error("allocating _tmpscreen2 failed");++#ifdef USE_OSD+	_osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,+						_hwscreen->w,+						_hwscreen->h,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);+	if (_osdSurface == NULL)+		error("allocating _osdSurface failed");+	SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey);+#endif++	// keyboard cursor control, some other better place for it?+	_km.x_max = _videoMode.screenWidth * _videoMode.scaleFactor - 1;+	_km.y_max = effectiveScreenHeight() - 1;+	_km.delay_time = 25;+	_km.last_time = 0;++	return true;+}++void OSystem_IPOD::unloadGFXMode() {+	if (_screen) {+		SDL_FreeSurface(_screen);+		_screen = NULL;+	}++	if (_hwscreen) {+		SDL_FreeSurface(_hwscreen);+		_hwscreen = NULL;+	}++	if (_tmpscreen) {+		SDL_FreeSurface(_tmpscreen);+		_tmpscreen = NULL;+	}++	if (_tmpscreen2) {+		SDL_FreeSurface(_tmpscreen2);+		_tmpscreen2 = NULL;+	}++	if (_overlayscreen) {+		SDL_FreeSurface(_overlayscreen);+		_overlayscreen = NULL;+	}++#ifdef USE_OSD+	if (_osdSurface) {+		SDL_FreeSurface(_osdSurface);+		_osdSurface = NULL;+	}+#endif+	DestroyScalers();+}++bool OSystem_IPOD::hotswapGFXMode() {+	if (!_screen)+		return false;++	// Keep around the old _screen & _overlayscreen so we can restore the screen data+	// after the mode switch.+	SDL_Surface *old_screen = _screen;+	SDL_Surface *old_overlayscreen = _overlayscreen;+	_screen = NULL;+	_overlayscreen = NULL;++	// Release the HW screen surface+	SDL_FreeSurface(_hwscreen); _hwscreen = NULL;++	SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL;+	SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL;++#ifdef USE_OSD+	// Release the OSD surface+	SDL_FreeSurface(_osdSurface); _osdSurface = NULL;+#endif++	// Setup the new GFX mode+	if (!loadGFXMode()) {+		unloadGFXMode();++		_screen = old_screen;+		_overlayscreen = old_overlayscreen;++		return false;+	}++	// reset palette+	SDL_SetColors(_screen, _currentPalette, 0, 256);++	// Restore old screen content+	SDL_BlitSurface(old_screen, NULL, _screen, NULL);+	SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);++	// Free the old surfaces+	SDL_FreeSurface(old_screen);+	SDL_FreeSurface(old_overlayscreen);++	// Update cursor to new scale+	blitCursor();++	// Blit everything to the screen+	internUpdateScreen();++	return true;+}++void OSystem_IPOD::updateScreen() {+	assert (_transactionMode == kTransactionNone);++	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends++	internUpdateScreen();+}++void OSystem_IPOD::internUpdateScreen() {+#ifdef USE_COP+        ipod_cop_update_screen();+#else+        internUpdateScreen_Real();+#endif+}++void OSystem_IPOD::internUpdateScreen_Real() {+	SDL_Surface *srcSurf, *origSurf;+	int height, width;+	ScalerProc *scalerProc;+	double scale1;++#if defined (DEBUG) // definitions not available for non-DEBUG here. (needed this to compile in SYMBIAN32 & linux?)+	assert(_hwscreen != NULL);+	assert(_hwscreen->map->sw_data != NULL);+#endif++	// If the shake position changed, fill the dirty area with blackness+	if (_currentShakePos != _newShakePos) {+		SDL_Rect blackrect = {_hwScreenOffsetX, _hwScreenOffsetY,+			_videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor};++		if (_videoMode.aspectRatio && !_overlayVisible)+			blackrect.h = real2Aspect(blackrect.h - 1) + 1;++		SDL_FillRect(_hwscreen, &blackrect, 0);++		_currentShakePos = _newShakePos;++		_forceFull = true;+	}++	// Check whether the palette was changed in the meantime and update the+	// screen surface accordingly.+	if (_screen && _paletteDirtyEnd != 0) {+		SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart,+			_paletteDirtyStart,+			_paletteDirtyEnd - _paletteDirtyStart);++		_paletteDirtyEnd = 0;++		_forceFull = true;+	}++#ifdef USE_OSD+	// OSD visible (i.e. non-transparent)?+	if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {+		// Updated alpha value+		const int diff = SDL_GetTicks() - _osdFadeStartTime;+		if (diff > 0) {+			if (diff >= kOSDFadeOutDuration) {+				// Back to full transparency+				_osdAlpha = SDL_ALPHA_TRANSPARENT;+			} else {+				// Do a linear fade out...+				const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;+				_osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;+			}+			SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);+			_forceFull = true;+		}+	}+#endif++	if (!_overlayVisible) {+		origSurf = _screen;+		srcSurf = _tmpscreen;+		width = _videoMode.screenWidth;+		height = _videoMode.screenHeight;+		scalerProc = _scalerProc;+		scale1 = _videoMode.scaleFactor;+	} else {+		origSurf = _overlayscreen;+		srcSurf = _tmpscreen2;+		width = _videoMode.overlayWidth;+		height = _videoMode.overlayHeight;+		scalerProc = Normal1x;++		scale1 = 1.0;+	}++	// Force a full redraw if requested+	if (_forceFull) {+		_numDirtyRects = 1;+		_dirtyRectList[0].x = 0;+		_dirtyRectList[0].y = 0;+		_dirtyRectList[0].w = width;+		_dirtyRectList[0].h = height;+	} else+		undrawMouse();++	// Only draw anything if necessary+	if (_numDirtyRects > 0) {++		SDL_Rect *r;+		SDL_Rect dst;+		uint32 srcPitch, dstPitch;+		SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;++		for (r = _dirtyRectList; r != lastRect; ++r) {+			if(scalerProc == Scaleo5x) {+				// To scale by half, we should make sure x,y are even aligned+				if(r->x & 0x1) {+					r->x -= 1;+					r->w += 1;+				}+				if(r->y & 0x1) {+					r->y -= 1;+					r->h += 1;+				}+				if(r->w & 0x1) {+					r->w += 1;+				}+				if(r->h & 0x1) {+					r->h += 1;+				}+			}++			dst = *r;+			dst.x++;	// Shift rect by one since 2xSai needs to acces the data around+			dst.y++;	// any pixel to scale it, and we want to avoid mem access crashes.++			if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)+				error("SDL_BlitSurface failed: %s", SDL_GetError());+		}++		SDL_LockSurface(srcSurf);+		SDL_LockSurface(_hwscreen);++		srcPitch = srcSurf->pitch;+		dstPitch = _hwscreen->pitch;++		for (r = _dirtyRectList; r != lastRect; ++r) {+			register int dst_y = r->y + _currentShakePos;+			register int dst_h = 0;+			register int orig_dst_y = 0;+			register int rx1 = r->x * scale1;++			if (dst_y < height) {+				dst_h = r->h;+				if (dst_h > height - dst_y)+					dst_h = height - dst_y;++				orig_dst_y = dst_y;+				dst_y = dst_y * scale1;++				if (_videoMode.aspectRatio && !_overlayVisible)+					dst_y = real2Aspect(dst_y);++				assert(scalerProc != NULL);+				scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,+						   (byte *)_hwscreen->pixels + (rx1 + _hwScreenOffsetX) * 2 + (dst_y + _hwScreenOffsetY) * dstPitch, dstPitch, r->w, dst_h);+			}++			r->x = rx1 + _hwScreenOffsetX;+			r->y = dst_y + _hwScreenOffsetY;+			r->w = r->w * scale1;+			r->h = dst_h * scale1;++		}+		SDL_UnlockSurface(srcSurf);+		SDL_UnlockSurface(_hwscreen);++		// Readjust the dirty rect list in case we are doing a full update.+		// This is necessary if shaking is active.+		if (_forceFull) {+			_dirtyRectList[0].y = _hwScreenOffsetY;+			_dirtyRectList[0].h = effectiveScreenHeight();+		}++		drawMouse();++#ifdef USE_OSD+		if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {+			SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);+		}+#endif+		// Finally, blit all our changes to the screen+		SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);+	} else {+		drawMouse();+		if (_numDirtyRects)+			SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);+	}++	_numDirtyRects = 0;+	_forceFull = false;+}++bool OSystem_IPOD::saveScreenshot(const char *filename) {+	assert(_hwscreen != NULL);++	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends+	return SDL_SaveBMP(_hwscreen, filename) == 0;+}++void OSystem_IPOD::setFullscreenMode(bool enable) {+	Common::StackLock lock(_graphicsMutex);+	+	if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)+		return;++	if (_transactionMode == kTransactionActive) {+		_videoMode.fullscreen = enable;+		_transactionDetails.needHotswap = true;+	}+}++void OSystem_IPOD::setAspectRatioCorrection(bool enable) {+	Common::StackLock lock(_graphicsMutex);++	if (_oldVideoMode.setup && _oldVideoMode.aspectRatio == enable)+		return;++	if (_transactionMode == kTransactionActive) {+		_videoMode.aspectRatio = enable;+		_transactionDetails.needHotswap = true;+	}+}++void OSystem_IPOD::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {+	assert (_transactionMode == kTransactionNone);+	assert(src);++	if (_screen == NULL) {+		warning("OSystem_IPOD::copyRectToScreen: _screen == NULL");+		return;+	}++	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends++	assert(x >= 0 && x < _videoMode.screenWidth);+	assert(y >= 0 && y < _videoMode.screenHeight);+	assert(h > 0 && y + h <= _videoMode.screenHeight);+	assert(w > 0 && x + w <= _videoMode.screenWidth);++	if (((long)src & 3) == 0 && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&+			w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {+		/* Special, optimized case for full screen updates.+		 * It tries to determine what areas were actually changed,+		 * and just updates those, on the actual display. */+		addDirtyRgnAuto(src);+	} else {+		/* Clip the coordinates */+		if (x < 0) {+			w += x;+			src -= x;+			x = 0;+		}++		if (y < 0) {+			h += y;+			src -= y * pitch;+			y = 0;+		}++		if (w > _videoMode.screenWidth - x) {+			w = _videoMode.screenWidth - x;+		}++		if (h > _videoMode.screenHeight - y) {+			h = _videoMode.screenHeight - y;+		}++		if (w <= 0 || h <= 0)+			return;++		_cksumValid = false;+		addDirtyRect(x, y, w, h);+	}++	// Try to lock the screen surface+	if (SDL_LockSurface(_screen) == -1)+		error("SDL_LockSurface failed: %s", SDL_GetError());++	byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;++	if (_videoMode.screenWidth == pitch && pitch == w) {+		memcpy(dst, src, h*w);+	} else {+		do {+			memcpy(dst, src, w);+			src += pitch;+			dst += _videoMode.screenWidth;+		} while (--h);+	}++	// Unlock the screen surface+	SDL_UnlockSurface(_screen);+}++Graphics::Surface *OSystem_IPOD::lockScreen() {+	assert (_transactionMode == kTransactionNone);++	// Lock the graphics mutex+	lockMutex(_graphicsMutex);++	// paranoia check+	assert(!_screenIsLocked);+	_screenIsLocked = true;++	// Try to lock the screen surface+	if (SDL_LockSurface(_screen) == -1)+		error("SDL_LockSurface failed: %s", SDL_GetError());++	_framebuffer.pixels = _screen->pixels;+	_framebuffer.w = _screen->w;+	_framebuffer.h = _screen->h;+	_framebuffer.pitch = _screen->pitch;+	_framebuffer.bytesPerPixel = 1;++	return &_framebuffer;+}++void OSystem_IPOD::unlockScreen() {+	assert (_transactionMode == kTransactionNone);++	// paranoia check+	assert(_screenIsLocked);+	_screenIsLocked = false;++	// Unlock the screen surface+	SDL_UnlockSurface(_screen);++	// Trigger a full screen update+	_forceFull = true;++	// Finally unlock the graphics mutex+	unlockMutex(_graphicsMutex);+}++void OSystem_IPOD::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {+	if (_forceFull)+		return;++	if (_numDirtyRects == NUM_DIRTY_RECT) {+		_forceFull = true;+		return;+	}++	int height, width;++	if (!_overlayVisible && !realCoordinates) {+		width = _videoMode.screenWidth;+		height = _videoMode.screenHeight;+	} else {+		width = _videoMode.overlayWidth;+		height = _videoMode.overlayHeight;+	}++	// Extend the dirty region by 1 pixel for scalers+	// that "smear" the screen, e.g. 2xSAI+	if (!realCoordinates) {+		x--;+		y--;+		w+=2;+		h+=2;+	}++	// clip+	if (x < 0) {+		w += x;+		x = 0;+	}++	if (y < 0) {+		h += y;+		y=0;+	}++	if (w > width - x) {+		w = width - x;+	}++	if (h > height - y) {+		h = height - y;+	}++	if (w == width && h == height) {+		_forceFull = true;+		return;+	}++	if (w > 0 && h > 0) {+		SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];++		r->x = x;+		r->y = y;+		r->w = w;+		r->h = h;+	}+}+++void OSystem_IPOD::makeChecksums(const byte *buf) {+	assert(buf);+	uint32 *sums = _dirtyChecksums;+	uint x,y;+	const uint last_x = (uint)_videoMode.screenWidth / 8;+	const uint last_y = (uint)_videoMode.screenHeight / 8;++	const uint BASE = 65521; /* largest prime smaller than 65536 */++	/* the 8x8 blocks in buf are enumerated starting in the top left corner and+	 * reading each line at a time from left to right */+	for (y = 0; y != last_y; y++, buf += _videoMode.screenWidth * (8 - 1))+		for (x = 0; x != last_x; x++, buf += 8) {+			// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).+			// This computes the Adler32 checksum of a 8x8 pixel block. Note+			// that we can do the modulo operation (which is the slowest part)+			// of the algorithm) at the end, instead of doing each iteration,+			// since we only have 64 iterations in total - and thus s1 and+			// s2 can't overflow anyway.+			uint32 s1 = 1;+			uint32 s2 = 0;+			const byte *ptr = buf;+			for (int subY = 0; subY < 8; subY++) {+				for (int subX = 0; subX < 8; subX++) {+					s1 += ptr[subX];+					s2 += s1;+				}+				ptr += _videoMode.screenWidth;+			}++			s1 %= BASE;+			s2 %= BASE;++			/* output the checksum for this block */+			*sums++ =  (s2 << 16) + s1;+	}+}++void OSystem_IPOD::addDirtyRgnAuto(const byte *buf) {+	assert(buf);+	assert(((long)buf & 3) == 0);++	/* generate a table of the checksums */+	makeChecksums(buf);++	if (!_cksumValid) {+		_forceFull = true;+		_cksumValid = true;+	}++	/* go through the checksum list, compare it with the previous checksums,+		 and add all dirty rectangles to a list. try to combine small rectangles+		 into bigger ones in a simple way */+	if (!_forceFull) {+		int x, y, w;+		uint32 *ck = _dirtyChecksums;++		for (y = 0; y != _videoMode.screenHeight / 8; y++) {+			for (x = 0; x != _videoMode.screenWidth / 8; x++, ck++) {+				if (ck[0] != ck[_cksumNum]) {+					/* found a dirty 8x8 block, now go as far to the right as possible,+						 and at the same time, unmark the dirty status by setting old to new. */+					w=0;+					do {+						ck[w + _cksumNum] = ck[w];+						w++;+					} while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);++					addDirtyRect(x * 8, y * 8, w * 8, 8);++					if (_forceFull)+						goto get_out;+				}+			}+		}+	} else {+		get_out:;+		/* Copy old checksums to new */+		memcpy(_dirtyChecksums + _cksumNum, _dirtyChecksums, _cksumNum * sizeof(uint32));+	}+}++int16 OSystem_IPOD::getHeight() {+	return _videoMode.screenHeight;+}++int16 OSystem_IPOD::getWidth() {+	return _videoMode.screenWidth;+}++void OSystem_IPOD::setPalette(const byte *colors, uint start, uint num) {+	assert(colors);++	// Setting the palette before _screen is created is allowed - for now -+	// since we don't actually set the palette until the screen is updated.+	// But it could indicate a programming error, so let's warn about it.++	if (!_screen)+		warning("OSystem_IPOD::setPalette: _screen == NULL");++	const byte *b = colors;+	uint i;+	SDL_Color *base = _currentPalette + start;+	for (i = 0; i < num; i++) {+		base[i].r = b[0];+		base[i].g = b[1];+		base[i].b = b[2];+		b += 4;+	}++	if (start < _paletteDirtyStart)+		_paletteDirtyStart = start;++	if (start + num > _paletteDirtyEnd)+		_paletteDirtyEnd = start + num;++	// Some games blink cursors with palette+	if (_cursorPaletteDisabled)+		blitCursor();+}++void OSystem_IPOD::grabPalette(byte *colors, uint start, uint num) {+	assert(colors);+	const SDL_Color *base = _currentPalette + start;++	for (uint i = 0; i < num; ++i) {+		colors[i * 4] = base[i].r;+		colors[i * 4 + 1] = base[i].g;+		colors[i * 4 + 2] = base[i].b;+		colors[i * 4 + 3] = 0xFF;+	}+}++void OSystem_IPOD::setCursorPalette(const byte *colors, uint start, uint num) {+	assert(colors);+	const byte *b = colors;+	uint i;+	SDL_Color *base = _cursorPalette + start;+	for (i = 0; i < num; i++) {+		base[i].r = b[0];+		base[i].g = b[1];+		base[i].b = b[2];+		b += 4;+	}++	_cursorPaletteDisabled = false;++	blitCursor();+}++void OSystem_IPOD::setShakePos(int shake_pos) {+	assert (_transactionMode == kTransactionNone);++	_newShakePos = shake_pos;+}+++#pragma mark -+#pragma mark --- Overlays ---+#pragma mark -++void OSystem_IPOD::showOverlay() {+	assert (_transactionMode == kTransactionNone);++	int x, y;++	if (_overlayVisible)+		return;++	_overlayVisible = true;++	// Since resolution could change, put mouse to adjusted position+	// Fixes bug #1349059+	x = _mouseCurState.x * _videoMode.scaleFactor;+	if (_videoMode.aspectRatio)+		y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor;+	else+		y = _mouseCurState.y * _videoMode.scaleFactor;++	warpMouse(x, y);++	clearOverlay();+}++void OSystem_IPOD::hideOverlay() {+	assert (_transactionMode == kTransactionNone);++	if (!_overlayVisible)+		return;++	int x, y;++	_overlayVisible = false;++	// Since resolution could change, put mouse to adjusted position+	// Fixes bug #1349059+	x = _mouseCurState.x / _videoMode.scaleFactor;+	y = _mouseCurState.y / _videoMode.scaleFactor;+	if (_videoMode.aspectRatio)+		y = aspect2Real(y);++	warpMouse(x, y);++	clearOverlay();++	_forceFull = true;+}++void OSystem_IPOD::clearOverlay() {+	//assert (_transactionMode == kTransactionNone);++	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends++	if (!_overlayVisible)+		return;++	// Clear the overlay by making the game screen "look through" everywhere.+	SDL_Rect src, dst;+	src.x = src.y = 0;+	dst.x = dst.y = 1;+	src.w = dst.w = _videoMode.screenWidth;+	src.h = dst.h = _videoMode.screenHeight;+	if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)+		error("SDL_BlitSurface failed: %s", SDL_GetError());++	SDL_LockSurface(_tmpscreen);+	SDL_LockSurface(_overlayscreen);+	_scalerProc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, _tmpscreen->pitch,+	(byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);++	SDL_UnlockSurface(_tmpscreen);+	SDL_UnlockSurface(_overlayscreen);++	_forceFull = true;+}++void OSystem_IPOD::grabOverlay(OverlayColor *buf, int pitch) {+	assert (_transactionMode == kTransactionNone);++	if (_overlayscreen == NULL)+		return;++	if (SDL_LockSurface(_overlayscreen) == -1)+		error("SDL_LockSurface failed: %s", SDL_GetError());++	byte *src = (byte *)_overlayscreen->pixels;+	int h = _videoMode.overlayHeight;+	do {+		memcpy(buf, src, _videoMode.overlayWidth * 2);+		src += _overlayscreen->pitch;+		buf += pitch;+	} while (--h);++	SDL_UnlockSurface(_overlayscreen);+}++void OSystem_IPOD::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {+	assert (_transactionMode == kTransactionNone);++	if (_overlayscreen == NULL)+		return;++	// Clip the coordinates+	if (x < 0) {+		w += x;+		buf -= x;+		x = 0;+	}++	if (y < 0) {+		h += y; buf -= y * pitch;+		y = 0;+	}++	if (w > _videoMode.overlayWidth - x) {+		w = _videoMode.overlayWidth - x;+	}++	if (h > _videoMode.overlayHeight - y) {+		h = _videoMode.overlayHeight - y;+	}++	if (w <= 0 || h <= 0)+		return;++	// Mark the modified region as dirty+	_cksumValid = false;+	addDirtyRect(x, y, w, h);++	if (SDL_LockSurface(_overlayscreen) == -1)+		error("SDL_LockSurface failed: %s", SDL_GetError());++	byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;+	do {+		memcpy(dst, buf, w * 2);+		dst += _overlayscreen->pitch;+		buf += pitch;+	} while (--h);++	SDL_UnlockSurface(_overlayscreen);+}+++#pragma mark -+#pragma mark --- Mouse ---+#pragma mark -++bool OSystem_IPOD::showMouse(bool visible) {+	if (_mouseVisible == visible)+		return visible;++	bool last = _mouseVisible;+	_mouseVisible = visible;++	return last;+}++void OSystem_IPOD::setMousePos(int x, int y) {+	if (x != _mouseCurState.x || y != _mouseCurState.y) {+		_mouseCurState.x = x;+		_mouseCurState.y = y;+	}+}++void OSystem_IPOD::warpMouse(int x, int y) {+	int y1 = y;++	if (_videoMode.aspectRatio && !_overlayVisible)+		y1 = real2Aspect(y);++	if (_mouseCurState.x != x || _mouseCurState.y != y) {+		if (!_overlayVisible)+			SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);+		else+			SDL_WarpMouse(x, y1);++		// SDL_WarpMouse() generates a mouse movement event, so+		// setMousePos() would be called eventually. However, the+		// cannon script in CoMI calls this function twice each time+		// the cannon is reloaded. Unless we update the mouse position+		// immediately the second call is ignored, causing the cannon+		// to change its aim.++		setMousePos(x, y);+	}+}++void OSystem_IPOD::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {+	if (w == 0 || h == 0)+		return;++	_mouseCurState.hotX = hotspot_x;+	_mouseCurState.hotY = hotspot_y;++	_mouseKeyColor = keycolor;++	_cursorTargetScale = cursorTargetScale;++	if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {+		_mouseCurState.w = w;+		_mouseCurState.h = h;++		if (_mouseOrigSurface)+			SDL_FreeSurface(_mouseOrigSurface);++		// Allocate bigger surface because AdvMame2x adds black pixel at [0,0]+		_mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,+						_mouseCurState.w + 2,+						_mouseCurState.h + 2,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);++		if (_mouseOrigSurface == NULL)+			error("allocating _mouseOrigSurface failed");+		SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);+	}++	free(_mouseData);++	_mouseData = (byte *)malloc(w * h);+	memcpy(_mouseData, buf, w * h);+	blitCursor();+}++void OSystem_IPOD::blitCursor() {+	byte *dstPtr;+	const byte *srcPtr = _mouseData;+	byte color;+	int w, h, i, j;++	if (!_mouseOrigSurface || !_mouseData)+		return;++	w = _mouseCurState.w;+	h = _mouseCurState.h;++	SDL_LockSurface(_mouseOrigSurface);++	// Make whole surface transparent+	for (i = 0; i < h + 2; i++) {+		dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i;+		for (j = 0; j < w + 2; j++) {+			*(uint16 *)dstPtr = kMouseColorKey;+			dstPtr += 2;+		}+	}++	// Draw from [1,1] since AdvMame2x adds artefact at 0,0+	dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2;++	SDL_Color *palette;++	if (_cursorPaletteDisabled)+		palette = _currentPalette;+	else+		palette = _cursorPalette;++	for (i = 0; i < h; i++) {+		for (j = 0; j < w; j++) {+			color = *srcPtr;+			if (color != _mouseKeyColor) {	// transparent, don't draw+				*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,+					palette[color].r, palette[color].g, palette[color].b);+			}+			dstPtr += 2;+			srcPtr++;+		}+		dstPtr += _mouseOrigSurface->pitch - w * 2;+	}++	int rW, rH;++	if (_cursorTargetScale >= _videoMode.scaleFactor) {+		// The cursor target scale is greater or equal to the scale at+		// which the rest of the screen is drawn. We do not downscale+		// the cursor image, we draw it at its original size. It will+		// appear too large on screen.++		rW = w;+		rH = h;+		_mouseCurState.rHotX = _mouseCurState.hotX;+		_mouseCurState.rHotY = _mouseCurState.hotY;++		// The virtual dimensions may be larger than the original.++		_mouseCurState.vW = w * _cursorTargetScale / _videoMode.scaleFactor;+		_mouseCurState.vH = h * _cursorTargetScale / _videoMode.scaleFactor;+		_mouseCurState.vHotX = _mouseCurState.hotX * _cursorTargetScale /+			_videoMode.scaleFactor;+		_mouseCurState.vHotY = _mouseCurState.hotY * _cursorTargetScale /+			_videoMode.scaleFactor;+	} else {+		// The cursor target scale is smaller than the scale at which+		// the rest of the screen is drawn. We scale up the cursor+		// image to make it appear correct.++		rW = w * _videoMode.scaleFactor / _cursorTargetScale;+		rH = h * _videoMode.scaleFactor / _cursorTargetScale;+		_mouseCurState.rHotX = _mouseCurState.hotX * _videoMode.scaleFactor /+			_cursorTargetScale;+		_mouseCurState.rHotY = _mouseCurState.hotY * _videoMode.scaleFactor /+			_cursorTargetScale;++		// The virtual dimensions will be the same as the original.++		_mouseCurState.vW = w;+		_mouseCurState.vH = h;+		_mouseCurState.vHotX = _mouseCurState.hotX;+		_mouseCurState.vHotY = _mouseCurState.hotY;+	}++	if (_videoMode.aspectRatio && _cursorTargetScale == 1) {+		rH = real2Aspect(rH - 1) + 1;+		_mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);+	}++	if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) {+		_mouseCurState.rW = rW;+		_mouseCurState.rH = rH;++		if (_mouseSurface)+			SDL_FreeSurface(_mouseSurface);++		_mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,+						_mouseCurState.rW,+						_mouseCurState.rH,+						16,+						_hwscreen->format->Rmask,+						_hwscreen->format->Gmask,+						_hwscreen->format->Bmask,+						_hwscreen->format->Amask);++		if (_mouseSurface == NULL)+			error("allocating _mouseSurface failed");++		SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);+	}++	SDL_LockSurface(_mouseSurface);++	ScalerProc *scalerProc;++	// If possible, use the same scaler for the cursor as for the rest of+	// the game. This only works well with the non-blurring scalers so we+	// actually only use the 1x, 1.5x, 2x and AdvMame scalers.++	scalerProc = Normal1x;++	scalerProc((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2,+		_mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch,+		_mouseCurState.w, _mouseCurState.h);++	SDL_UnlockSurface(_mouseSurface);+	SDL_UnlockSurface(_mouseOrigSurface);+}++void OSystem_IPOD::toggleMouseGrab() {+	if (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_OFF)+		SDL_WM_GrabInput(SDL_GRAB_ON);+	else+		SDL_WM_GrabInput(SDL_GRAB_OFF);+}++void OSystem_IPOD::undrawMouse() {+	const int x = _mouseBackup.x;+	const int y = _mouseBackup.y;++	// When we switch bigger overlay off mouse jumps. Argh!+	// This is intended to prevent undrawing offscreen mouse+	if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight)) {+		return;+	}++	if (_mouseBackup.w != 0 && _mouseBackup.h != 0)+		addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h);+}++void OSystem_IPOD::drawMouse() {+	if (!_mouseVisible || !_mouseSurface) {+		_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;+		return;+	}++	SDL_Rect dst;+	double scale;+	int width, height;+	int hotX, hotY;++	dst.x = _mouseCurState.x;+	dst.y = _mouseCurState.y;++	if (!_overlayVisible) {+		scale = _videoMode.scaleFactor;+		width = _videoMode.screenWidth;+		height = _videoMode.screenHeight;+		dst.w = _mouseCurState.vW;+		dst.h = _mouseCurState.vH;+		hotX = _mouseCurState.vHotX;+		hotY = _mouseCurState.vHotY;+	} else {+		scale = 1.0;+		width = _videoMode.overlayWidth;+		height = _videoMode.overlayHeight;+		dst.w = _mouseCurState.rW;+		dst.h = _mouseCurState.rH;+		hotX = _mouseCurState.rHotX;+		hotY = _mouseCurState.rHotY;+	}++	// The mouse is undrawn using virtual coordinates, i.e. they may be+	// scaled and aspect-ratio corrected.++	_mouseBackup.x = dst.x - hotX;+	_mouseBackup.y = dst.y - hotY;+	_mouseBackup.w = dst.w;+	_mouseBackup.h = dst.h;++	// We draw the pre-scaled cursor image, so now we need to adjust for+	// scaling, shake position and aspect ratio correction manually.++	if (!_overlayVisible) {+		dst.y += _currentShakePos;+	}++	if (_videoMode.aspectRatio && !_overlayVisible)+		dst.y = real2Aspect(dst.y);++	dst.x = scale * dst.x - _mouseCurState.rHotX + _hwScreenOffsetX;+	dst.y = scale * dst.y - _mouseCurState.rHotY + _hwScreenOffsetY;+	dst.w = _mouseCurState.rW;+	dst.h = _mouseCurState.rH;++	// Note that SDL_BlitSurface() and addDirtyRect() will both perform any+	// clipping necessary++	if (SDL_BlitSurface(_mouseSurface, NULL, _hwscreen, &dst) != 0)+		error("SDL_BlitSurface failed: %s", SDL_GetError());++	// The screen will be updated using real surface coordinates, i.e.+	// they will not be scaled or aspect-ratio corrected.++	addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);+}++#pragma mark -+#pragma mark --- On Screen Display ---+#pragma mark -++#ifdef USE_OSD+void OSystem_IPOD::displayMessageOnOSD(const char *msg) {+	assert (_transactionMode == kTransactionNone);+	assert(msg);++	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends++	uint i;++	// Lock the OSD surface for drawing+	if (SDL_LockSurface(_osdSurface))+		error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());++	Graphics::Surface dst;+	dst.pixels = _osdSurface->pixels;+	dst.w = _osdSurface->w;+	dst.h = _osdSurface->h;+	dst.pitch = _osdSurface->pitch;+	dst.bytesPerPixel = _osdSurface->format->BytesPerPixel;++	// The font we are going to use:+	const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);++	// Clear everything with the "transparent" color, i.e. the colorkey+	SDL_FillRect(_osdSurface, 0, kOSDColorKey);++	// Split the message into separate lines.+	Common::StringList lines;+	const char *ptr;+	for (ptr = msg; *ptr; ++ptr) {+		if (*ptr == '\n') {+			lines.push_back(Common::String(msg, ptr - msg));+			msg = ptr + 1;+		}+	}+	lines.push_back(Common::String(msg, ptr - msg));++	// Determine a rect which would contain the message string (clipped to the+	// screen dimensions).+	const int vOffset = 6;+	const int lineSpacing = 1;+	const int lineHeight = font->getFontHeight() + 2 * lineSpacing;+	int width = 0;+	int height = lineHeight * lines.size() + 2 * vOffset;+	for (i = 0; i < lines.size(); i++) {+		width = MAX(width, font->getStringWidth(lines[i]) + 14);+	}++	// Clip the rect+	if (width > dst.w)+		width = dst.w;+	if (height > dst.h)+		height = dst.h;++	// Draw a dark gray rect+	// TODO: Rounded corners ? Border?+	SDL_Rect osdRect;+	osdRect.x = (dst.w - width) / 2;+	osdRect.y = (dst.h - height) / 2;+	osdRect.w = width;+	osdRect.h = height;+	SDL_FillRect(_osdSurface, &osdRect, SDL_MapRGB(_osdSurface->format, 64, 64, 64));++	// Render the message, centered, and in white+	for (i = 0; i < lines.size(); i++) {+		font->drawString(&dst, lines[i],+							osdRect.x, osdRect.y + i * lineHeight + vOffset + lineSpacing, osdRect.w,+							SDL_MapRGB(_osdSurface->format, 255, 255, 255),+							Graphics::kTextAlignCenter);+	}++	// Finished drawing, so unlock the OSD surface again+	SDL_UnlockSurface(_osdSurface);++	// Init the OSD display parameters, and the fade out+	_osdAlpha = SDL_ALPHA_TRANSPARENT +  kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;+	_osdFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay;+	SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);++	// Ensure a full redraw takes place next time the screen is updated+	_forceFull = true;+}+#endif+++#pragma mark -+#pragma mark --- Misc ---+#pragma mark -+Index: backends/platform/ipod/cop.cpp===================================================================--- backends/platform/ipod/cop.cpp	(revision 0)+++ backends/platform/ipod/cop.cpp	(revision 0)@@ -0,0 +1,58 @@++#include "backends/platform/ipod/sdl.h"++#ifdef USE_COP++#define COP_HANDLER            0x4001501C+#define COP_STATUS            0x40015020+#define COP_CONTROL            0x60007004+ +#define COP_RUNNING            (1 << 0)+#define COP_LINE_REQ        (1 << 1)+#define COP_LINE_REQ_CLEAR    (1 << 2)++#define outl(a, b) \+	(*(volatile unsigned int *)(b) = (a))++#define inl(a) \+	(*(volatile unsigned int *)(a))++#define ipod_cop_clear_frameready() \+	outl(inl(COP_STATUS) &~ COP_LINE_REQ_CLEAR, COP_STATUS)++static OSystem_IPOD* graphics_system = NULL;++void ipod_cop_update_screen() {+	outl(inl(COP_STATUS) | COP_LINE_REQ, COP_STATUS);+}++void ipod_cop_sync_screen()+{+	assert(graphics_system);+	while (inl(COP_STATUS) & COP_RUNNING) // COP is active+	{+		// Get stuck in loop until told to update screen+		while ((inl(COP_STATUS) & COP_LINE_REQ) == 0);+		graphics_system->internUpdateScreen_Real();+		outl(inl(COP_STATUS) &~ COP_LINE_REQ, COP_STATUS);+	}	+}++void ipod_cop_execute(void (*function)())+{+	outl((unsigned int)function, COP_HANDLER);+	outl(0x0, COP_CONTROL);+}++void ipod_init_cop(OSystem_IPOD *ipod_g_system)+{+	printf("Starting ipod_init_cop\n");+	graphics_system = ipod_g_system;+	ipod_cop_clear_frameready();+	ipod_cop_execute(ipod_cop_sync_screen);	+	outl(COP_RUNNING, COP_STATUS); // Start COP?+	printf("Ending ipod_init_cop\n");+}++#endif //USE_COP+Index: backends/platform/ipod/sdl.cpp===================================================================--- backends/platform/ipod/sdl.cpp	(revision 0)+++ backends/platform/ipod/sdl.cpp	(revision 0)@@ -0,0 +1,404 @@+/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/sdl.cpp $+ * $Id: sdl.cpp 35066 2008-11-14 23:10:14Z lordhoto $+ *+ */++#include "backends/platform/ipod/sdl.h"+#include "common/archive.h"+#include "common/config-manager.h"+#include "common/events.h"+#include "common/util.h"++#include "backends/saves/posix/posix-saves.h"+#include "backends/timer/default/default-timer.h"+#include "sound/mixer_intern.h"++#include "icons/scummvm.xpm"++#include <time.h>	// for getTimeAndDate()++/*+ * Include header files needed for the getFilesystemFactory() method.+ */+#include "backends/fs/posix/posix-fs-factory.h"++#define DEFAULT_CONFIG_FILE ".scummvmrc"++static Uint32 timer_handler(Uint32 interval, void *param) {+	((DefaultTimerManager *)param)->handler();+	return interval;+}++void OSystem_IPOD::initBackend() {+	assert(!_inited);++	int joystick_num = -1;+	uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_TIMER;++	if (ConfMan.hasKey("disable_sdl_parachute"))+		sdlFlags |= SDL_INIT_NOPARACHUTE;++	if (joystick_num > -1)+		sdlFlags |= SDL_INIT_JOYSTICK;++	if (SDL_Init(sdlFlags) == -1) {+		error("Could not initialize SDL: %s", SDL_GetError());+	}+	if (ConfMan.hasKey("rotation_modulation"))+		_rotation_modulation = ConfMan.getInt("rotation_modulation");+	else+		_rotation_modulation = 180;++	_graphicsMutex = createMutex();++	SDL_ShowCursor(SDL_DISABLE);++	// Enable unicode support if possible+	SDL_EnableUNICODE(1);++	memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));+	memset(&_videoMode, 0, sizeof(_videoMode));+	memset(&_transactionDetails, 0, sizeof(_transactionDetails));++	_cksumValid = false;+	_videoMode.aspectRatio = false;++	SDL_Rect **rs = SDL_ListModes(0, SDL_SWSURFACE);+	if(rs == (SDL_Rect **)-1) {+		_videoMode.mode = GFX_NORMAL;+		_videoMode.scaleFactor = 1.0;+		_scalerProc = Normal1x;+	} else {+	       if((*rs)->w < 320 || (*rs)->h < 240) {+			_videoMode.mode = GFX_HALF;+			_videoMode.scaleFactor = 0.5;+			_scalerProc = Scaleo5x;+	       } else {+			_videoMode.mode = GFX_NORMAL;+			_videoMode.scaleFactor = 1.0;+			_scalerProc = Normal1x;+	       }+	}++	_modeFlags = 0;++	_videoMode.fullscreen = true;++	// Create the savefile manager, if none exists yet (we check for this to+	// allow subclasses to provide their own).+	if (_savefile == 0) {+		_savefile = new POSIXSaveFileManager();+	}++	// Create and hook up the mixer, if none exists yet (we check for this to+	// allow subclasses to provide their own).+	if (_mixer == 0) {+		setupMixer();+	}++	// Create and hook up the timer manager, if none exists yet (we check for+	// this to allow subclasses to provide their own).+	if (_timer == 0) {+		// Note: We could implement a custom SDLTimerManager by using+		// SDL_AddTimer. That might yield better timer resolution, but it would+		// also change the semantics of a timer: Right now, ScummVM timers+		// *never* run in parallel, due to the way they are implemented. If we+		// switched to SDL_AddTimer, each timer might run in a separate thread.+		// However, not all our code is prepared for that, so we can't just+		// switch. Still, it's a potential future change to keep in mind.+		_timer = new DefaultTimerManager();+		_timerID = SDL_AddTimer(10, &timer_handler, _timer);+	}++	// Invoke parent implementation of this method+	OSystem::initBackend();++	_inited = true;+}++OSystem_IPOD::OSystem_IPOD()+	:+#ifdef USE_OSD+	_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),+#endif+	_hwscreen(0), _screen(0), _tmpscreen(0),+	_overlayVisible(false),+	_overlayscreen(0), _tmpscreen2(0),+	_samplesPerSec(0),+	_cdrom(0), _scalerProc(0), _modeChanged(false), _screenChangeCount(0), _dirtyChecksums(0),+	_mouseVisible(false), _mouseDrawn(false), _mouseData(0), _mouseSurface(0),+	_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),+	_joystick(0),+	_currentShakePos(0), _newShakePos(0),+	_paletteDirtyStart(0), _paletteDirtyEnd(0),+	_fsFactory(0),+	_savefile(0),+	_mixer(0),+	_timer(0),+	_screenIsLocked(false),+	_graphicsMutex(0), _transactionMode(kTransactionNone) {++	// allocate palette storage+	_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);+	_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);++	_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;++	// reset mouse state+	memset(&_km, 0, sizeof(_km));+	memset(&_mouseCurState, 0, sizeof(_mouseCurState));++	_inited = false;+++	_fsFactory = new POSIXFilesystemFactory();++#ifdef USE_COP+	ipod_init_cop(this);+#endif++}++OSystem_IPOD::~OSystem_IPOD() {+	SDL_RemoveTimer(_timerID);+	closeMixer();++	free(_dirtyChecksums);+	free(_currentPalette);+	free(_cursorPalette);+	free(_mouseData);++	delete _savefile;+	delete _timer;+}++uint32 OSystem_IPOD::getMillis() {+	uint32 millis = SDL_GetTicks();+	getEventManager()->processMillis(millis);+	return millis;+}++void OSystem_IPOD::delayMillis(uint msecs) {+	SDL_Delay(msecs);+}++void OSystem_IPOD::getTimeAndDate(struct tm &t) const {+	time_t curTime = time(0);+	t = *localtime(&curTime);+}++Common::TimerManager *OSystem_IPOD::getTimerManager() {+	assert(_timer);+	return _timer;+}++Common::SaveFileManager *OSystem_IPOD::getSavefileManager() {+	assert(_savefile);+	return _savefile;+}++FilesystemFactory *OSystem_IPOD::getFilesystemFactory() {+	assert(_fsFactory);+	return _fsFactory;+}++void OSystem_IPOD::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {++#ifdef DATA_PATH+	// Add the global DATA_PATH to the directory search list+	// FIXME: We use depth = 4 for now, to match the old code. May want to change that+	Common::FSNode dataNode(DATA_PATH);+	if (dataNode.exists() && dataNode.isDirectory()) {+		s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority);+	}+#endif++}+++static Common::String getDefaultConfigFileName() {+	char configFile[MAXPATHLEN];+	// On UNIX type systems, by default we store the config file inside+	// to the HOME directory of the user.+	//+	// GP2X is Linux based but Home dir can be read only so do not use+	// it and put the config in the executable dir.+	//+	// On the iPhone, the home dir of the user when you launch the app+	// from the Springboard, is /. Which we don't want.+	const char *home = getenv("HOME");+	if (home != NULL && strlen(home) < MAXPATHLEN)+		snprintf(configFile, MAXPATHLEN, "%s/%s", home, DEFAULT_CONFIG_FILE);+	else+		strcpy(configFile, DEFAULT_CONFIG_FILE);++	return configFile;+}++Common::SeekableReadStream *OSystem_IPOD::openConfigFileForReading() {+	Common::FSNode file(getDefaultConfigFileName());+	return file.openForReading();+}++Common::WriteStream *OSystem_IPOD::openConfigFileForWriting() {+	Common::FSNode file(getDefaultConfigFileName());+	return file.openForWriting();+}++void OSystem_IPOD::setWindowCaption(const char *caption) {+	SDL_WM_SetCaption(caption, caption);+}++bool OSystem_IPOD::hasFeature(Feature f) {+	return+		(f == kFeatureFullscreenMode) ||+		(f == kFeatureAspectRatioCorrection) ||+		(f == kFeatureAutoComputeDirtyRects) ||+		(f == kFeatureCursorHasPalette) ||+		(f == kFeatureIconifyWindow);+}++void OSystem_IPOD::setFeatureState(Feature f, bool enable) {+	switch (f) {+	case kFeatureFullscreenMode:+		setFullscreenMode(enable);+		break;+	case kFeatureAspectRatioCorrection:+		setAspectRatioCorrection(enable);+		break;+	case kFeatureAutoComputeDirtyRects:+		if (enable)+			_modeFlags |= DF_WANT_RECT_OPTIM;+		else+			_modeFlags &= ~DF_WANT_RECT_OPTIM;+		break;+	case kFeatureIconifyWindow:+		if (enable)+			SDL_WM_IconifyWindow();+		break;+	default:+		break;+	}+}++bool OSystem_IPOD::getFeatureState(Feature f) {+	assert (_transactionMode == kTransactionNone);++	switch (f) {+	case kFeatureFullscreenMode:+		return _videoMode.fullscreen;+	case kFeatureAspectRatioCorrection:+		return _videoMode.aspectRatio;+	case kFeatureAutoComputeDirtyRects:+		return _modeFlags & DF_WANT_RECT_OPTIM;+	default:+		return false;+	}+}++void OSystem_IPOD::quit() {+	unloadGFXMode();+	deleteMutex(_graphicsMutex);++	SDL_ShowCursor(SDL_ENABLE);++	SDL_RemoveTimer(_timerID);+	closeMixer();++	free(_dirtyChecksums);+	free(_currentPalette);+	free(_cursorPalette);+	free(_mouseData);++	delete _savefile;+	delete _timer;++	SDL_Quit();++	delete getEventManager();++	exit(0);+}++OSystem::MutexRef OSystem_IPOD::createMutex(void) {+	return (MutexRef) SDL_CreateMutex();+}++void OSystem_IPOD::lockMutex(MutexRef mutex) {+	SDL_mutexP((SDL_mutex *) mutex);+}++void OSystem_IPOD::unlockMutex(MutexRef mutex) {+	SDL_mutexV((SDL_mutex *) mutex);+}++void OSystem_IPOD::deleteMutex(MutexRef mutex) {+	SDL_DestroyMutex((SDL_mutex *) mutex);+}++#pragma mark -+#pragma mark --- Audio ---+#pragma mark -++void OSystem_IPOD::setupMixer() {+	_samplesPerSec = 0;+	assert(!_mixer);+	_mixer = new Audio::MixerImpl(this);+	assert(_mixer);+}++void OSystem_IPOD::closeMixer() {+	if (_mixer)+		_mixer->setReady(false);+	delete _mixer;+	_mixer = NULL;+}++Audio::Mixer *OSystem_IPOD::getMixer() {+	assert(_mixer);+	return _mixer;+}++#pragma mark -+#pragma mark --- CD Audio ---+#pragma mark -++bool OSystem_IPOD::openCD(int drive) {+	_cdrom = NULL;+}++void OSystem_IPOD::stopCD() {+	return;+}++void OSystem_IPOD::playCD(int track, int num_loops, int start_frame, int duration) {+	return;+}++bool OSystem_IPOD::pollCD() {+	return false;+}++void OSystem_IPOD::updateCD() {+	return;+}Index: backends/platform/ipod/main.cpp===================================================================--- backends/platform/ipod/main.cpp	(revision 0)+++ backends/platform/ipod/main.cpp	(revision 0)@@ -0,0 +1,45 @@+/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/main.cpp $+ * $Id: main.cpp 30664 2008-01-27 19:47:41Z jvprat $+ *+ */++#include "backends/platform/ipod/sdl.h"+#include "backends/plugins/sdl/sdl-provider.h"+#include "base/main.h"++int main(int argc, char *argv[]) {++	// Create our OSystem instance+	g_system = new OSystem_IPOD();+	assert(g_system);++#ifdef DYNAMIC_MODULES+	PluginManager::instance().addPluginProvider(new SDLPluginProvider());+#endif++	// Invoke the actual ScummVM main entry point:+	int res = scummvm_main(argc, argv);+	g_system->quit();	// TODO: Consider removing / replacing this!+	return res;+}+Index: backends/platform/ipod/events.cpp===================================================================--- backends/platform/ipod/events.cpp	(revision 0)+++ backends/platform/ipod/events.cpp	(revision 0)@@ -0,0 +1,440 @@+/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/events.cpp $+ * $Id: events.cpp 35062 2008-11-14 22:08:10Z lordhoto $+ *+ */++#include "backends/platform/ipod/sdl.h"+#include "common/util.h"+#include "common/events.h"++static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode)+{+	if (key >= SDLK_F1 && key <= SDLK_F9) {+		return key - SDLK_F1 + Common::ASCII_F1;+	} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {+		return key - SDLK_KP0 + '0';+	} else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {+		return key;+	} else if (unicode) {+		return unicode;+	} else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {+		return key & ~0x20;+	} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {+		return 0;+	}+	return key;+}++void OSystem_IPOD::fillMouseEvent(Common::Event &event, int x, int y) {+	event.mouse.x = x;+	event.mouse.y = y;++	// Update the "keyboard mouse" coords+	_km.x = x;+	_km.y = y;++	// Adjust for the screen scaling+	if (!_overlayVisible) {+		event.mouse.x /= _videoMode.scaleFactor;+		event.mouse.y /= _videoMode.scaleFactor;+		if (_videoMode.aspectRatio)+			event.mouse.y = aspect2Real(event.mouse.y);+	}+}++void OSystem_IPOD::handleKbdMouse() {+	uint32 curTime = getMillis();+	if (curTime >= _km.last_time + _km.delay_time) {+		_km.last_time = curTime;+		if (_km.x_down_count == 1) {+			_km.x_down_time = curTime;+			_km.x_down_count = 2;+		}+		if (_km.y_down_count == 1) {+			_km.y_down_time = curTime;+			_km.y_down_count = 2;+		}++		if (_km.x_vel || _km.y_vel) {+			if (_km.x_down_count) {+				if (curTime > _km.x_down_time + _km.delay_time * 12) {+					if (_km.x_vel > 0)+						_km.x_vel++;+					else+						_km.x_vel--;+				} else if (curTime > _km.x_down_time + _km.delay_time * 8) {+					if (_km.x_vel > 0)+						_km.x_vel = 5;+					else+						_km.x_vel = -5;+				}+			}+			if (_km.y_down_count) {+				if (curTime > _km.y_down_time + _km.delay_time * 12) {+					if (_km.y_vel > 0)+						_km.y_vel++;+					else+						_km.y_vel--;+				} else if (curTime > _km.y_down_time + _km.delay_time * 8) {+					if (_km.y_vel > 0)+						_km.y_vel = 5;+					else+						_km.y_vel = -5;+				}+			}++			_km.x += _km.x_vel;+			_km.y += _km.y_vel;++			if (_km.x < 0) {+				_km.x = 0;+				_km.x_vel = -1;+				_km.x_down_count = 1;+			} else if (_km.x > _km.x_max) {+				_km.x = _km.x_max;+				_km.x_vel = 1;+				_km.x_down_count = 1;+			}++			if (_km.y < 0) {+				_km.y = 0;+				_km.y_vel = -1;+				_km.y_down_count = 1;+			} else if (_km.y > _km.y_max) {+				_km.y = _km.y_max;+				_km.y_vel = 1;+				_km.y_down_count = 1;+			}++			SDL_WarpMouse((Uint16)_km.x, (Uint16)_km.y);+		}+	}+}++static byte SDLModToOSystemKeyFlags(SDLMod mod) {+	byte b = 0;+	if (mod & KMOD_SHIFT)+		b |= Common::KBD_SHIFT;+	if (mod & KMOD_ALT)+		b |= Common::KBD_ALT;+	if (mod & KMOD_CTRL)+		b |= Common::KBD_CTRL;++	return b;+}++bool OSystem_IPOD::pollEvent(Common::Event &event) {+	SDL_Event ev;+	int axis;+	byte b = 0;++	handleKbdMouse();++	// If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED+	if (_modeChanged) {+		_modeChanged = false;+		event.type = Common::EVENT_SCREEN_CHANGED;+		_screenChangeCount++;+		return true;+	}++	while (SDL_PollEvent(&ev)) {+		switch (ev.type) {+		case SDL_KEYDOWN:{+			b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());++			// Alt-Return and Alt-Enter toggle full screen mode+			if (b == Common::KBD_ALT && (ev.key.keysym.sym == SDLK_RETURN+			                  || ev.key.keysym.sym == SDLK_KP_ENTER)) {+				beginGFXTransaction();+					setFullscreenMode(!_videoMode.fullscreen);+				endGFXTransaction();+#ifdef USE_OSD+				if (_videoMode.fullscreen)+					displayMessageOnOSD("Fullscreen mode");+				else+					displayMessageOnOSD("Windowed mode");+#endif++				break;+			}++			// Alt-S: Create a screenshot+			if (b == Common::KBD_ALT && ev.key.keysym.sym == 's') {+				char filename[20];++				for (int n = 0;; n++) {+					SDL_RWops *file;++					sprintf(filename, "scummvm%05d.bmp", n);+					file = SDL_RWFromFile(filename, "r");+					if (!file)+						break;+					SDL_RWclose(file);+				}+				if (saveScreenshot(filename))+					printf("Saved '%s'\n", filename);+				else+					printf("Could not save screenshot!\n");+				break;+			}++			// Ctrl-m toggles mouse capture+			if (b == Common::KBD_CTRL && ev.key.keysym.sym == 'm') {+				toggleMouseGrab();+				break;+			}++#if defined(MACOSX)+			// On Macintosh', Cmd-Q quits+			if ((ev.key.keysym.mod & KMOD_META) && ev.key.keysym.sym == 'q') {+				event.type = Common::EVENT_QUIT;+				return true;+			}+#elif defined(UNIX)+			// On other unices, Control-Q quits+			if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') {+				event.type = Common::EVENT_QUIT;+				return true;+			}+#else+			// Ctrl-z and Alt-X quit+			if ((b == Common::KBD_CTRL && ev.key.keysym.sym == 'z') || (b == Common::KBD_ALT && ev.key.keysym.sym == 'x')) {+				event.type = Common::EVENT_QUIT;+				return true;+			}+#endif++			// Ctrl-Alt-<key> will change the GFX mode+			if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {+				// Swallow these key up events+				break;+			}++			const remapKeyResult remap_result = remapKey(ev, event);++			if (remap_result == IGNORE_KEYPRESS)+				continue;+			if (remap_result == EVENT_COMPLETED)+				return true;++			event.type = Common::EVENT_KEYDOWN;+			event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;+			event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);++			return true;+			}+		case SDL_KEYUP:+			{+			const remapKeyResult remap_result = remapKey(ev, event);++			if (remap_result == IGNORE_KEYPRESS)+				continue;+			if (remap_result == EVENT_COMPLETED)+				return true;++			event.type = Common::EVENT_KEYUP;+			event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;+			event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);+			b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());++			// Ctrl-Alt-<key> will change the GFX mode+			if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {+				// Swallow these key up events+				break;+			}++			return true;+			}++		case SDL_MOUSEMOTION:+			event.type = Common::EVENT_MOUSEMOVE;+			fillMouseEvent(event, ev.motion.x, ev.motion.y);++			setMousePos(event.mouse.x, event.mouse.y);+			return true;++		case SDL_MOUSEBUTTONDOWN:+			if (ev.button.button == SDL_BUTTON_LEFT)+			       event.type = Common::EVENT_LBUTTONDOWN;+			else if (ev.button.button == SDL_BUTTON_RIGHT)+			       event.type = Common::EVENT_RBUTTONDOWN;+#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN)+			else if (ev.button.button == SDL_BUTTON_WHEELUP)+			       event.type = Common::EVENT_WHEELUP;+			else if (ev.button.button == SDL_BUTTON_WHEELDOWN)+			       event.type = Common::EVENT_WHEELDOWN;+#endif+#if defined(SDL_BUTTON_MIDDLE)+			else if (ev.button.button == SDL_BUTTON_MIDDLE)+			       event.type = Common::EVENT_MBUTTONDOWN;+#endif+			else+			       break;++			fillMouseEvent(event, ev.button.x, ev.button.y);++			return true;++		case SDL_MOUSEBUTTONUP:+			if (ev.button.button == SDL_BUTTON_LEFT)+			       event.type = Common::EVENT_LBUTTONUP;+			else if (ev.button.button == SDL_BUTTON_RIGHT)+			       event.type = Common::EVENT_RBUTTONUP;+#if defined(SDL_BUTTON_MIDDLE)+			else if (ev.button.button == SDL_BUTTON_MIDDLE)+			       event.type = Common::EVENT_MBUTTONUP;+#endif+			else+			       break;+			fillMouseEvent(event, ev.button.x, ev.button.y);++			return true;++		case SDL_VIDEOEXPOSE:+			_forceFull = true;+			break;++		case SDL_QUIT:+			event.type = Common::EVENT_QUIT;+			return true;+		}+	}+	return false;+}++remapKeyResult OSystem_IPOD::remapKey(SDL_Event &ev, Common::Event &event) {+        static int rotate_modulation_counter = 0;++        if ((ev.key.keysym.sym == SDLK_m)) {+                if (ev.type == SDL_KEYDOWN) {+                        _km.y_vel = -1;+                        _km.y_down_count = 1;+                        event.type = Common::EVENT_MOUSEMOVE;+                } else if (ev.type == SDL_KEYUP) {+                        _km.y_vel = 0;+                        _km.y_down_count = 0;+                }+                handleKbdMouse();+                fillMouseEvent(event, _km.x, _km.y);+                return EVENT_COMPLETED;+        }++        if ((ev.key.keysym.sym == SDLK_w)) {+                if (ev.type == SDL_KEYDOWN) {+                        _km.x_vel = -1;+                        _km.x_down_count = 1;+                        event.type = Common::EVENT_MOUSEMOVE;+                } else if (ev.type == SDL_KEYUP) {+                        _km.x_vel = 0;+                        _km.x_down_count = 0;+                }+                handleKbdMouse();+                fillMouseEvent(event, _km.x, _km.y);+                return EVENT_COMPLETED;+        }++        if ((ev.key.keysym.sym == SDLK_f)) {+                if (ev.type == SDL_KEYDOWN) {+                        _km.x_vel = 1;+                        _km.x_down_count = 1;+                        event.type = Common::EVENT_MOUSEMOVE;+                } else if (ev.type == SDL_KEYUP) {+                        _km.x_vel = 0;+                        _km.x_down_count = 0;+                }+                handleKbdMouse();+                fillMouseEvent(event, _km.x, _km.y);+                return EVENT_COMPLETED;+        }++        if ((ev.key.keysym.sym == SDLK_d)) {+                if (ev.type == SDL_KEYDOWN) {+                        _km.y_vel = 1;+                        _km.y_down_count = 1;+                        event.type = Common::EVENT_MOUSEMOVE;+                } else if (ev.type == SDL_KEYUP) {+                        _km.y_vel = 0;+                        _km.y_down_count = 0;+                }+                handleKbdMouse();+                fillMouseEvent(event, _km.x, _km.y);+                return EVENT_COMPLETED;+        }++        if (ev.key.keysym.sym == SDLK_h) {+                if (ev.type == SDL_KEYDOWN)+                        event.type = Common::EVENT_KEYDOWN;+                if (ev.type == SDL_KEYUP)+                        event.type = Common::EVENT_KEYUP;+                event.kbd.keycode = Common::KEYCODE_F5;+                event.kbd.ascii = mapKey(SDLK_F5, ev.key.keysym.mod, 0);+                return EVENT_COMPLETED;+        }++        if (ev.key.keysym.sym == SDLK_RETURN) {+                if (ev.type == SDL_KEYDOWN)+                        event.type = Common::EVENT_LBUTTONDOWN;+                if (ev.type == SDL_KEYUP)+                        event.type = Common::EVENT_LBUTTONUP;+                fillMouseEvent(event, _km.x, _km.y);+                return EVENT_COMPLETED;+        }++        if (ev.key.keysym.sym == SDLK_l) {+                rotate_modulation_counter += 1;+                if(rotate_modulation_counter >= _rotation_modulation) {+                        rotate_modulation_counter = 0;+                        //event.type = Common::EVENT_LBUTTONDOWN;+                        //fillMouseEvent(event, _km.x, _km.y);++			event.type = Common::EVENT_KEYDOWN;+			event.kbd.keycode = Common::KEYCODE_ESCAPE;+			event.kbd.ascii = mapKey(SDLK_ESCAPE, ev.key.keysym.mod, 0);++			//Put an SDL KEYUP event on the queue+			SDL_Event keyup_event;+			keyup_event.type = SDL_KEYUP;+			keyup_event.key.state = SDL_RELEASED;+			keyup_event.key.keysym.sym = SDLK_ESCAPE;+			SDL_PushEvent(&keyup_event);++                        return EVENT_COMPLETED;+                }+                return IGNORE_KEYPRESS;+        }++        if (ev.key.keysym.sym == SDLK_r) {+                rotate_modulation_counter -= 1;+                if(rotate_modulation_counter <= -_rotation_modulation) {+                        rotate_modulation_counter = 0;+                        event.type = Common::EVENT_RBUTTONDOWN;+                        fillMouseEvent(event, _km.x, _km.y);+                        return EVENT_COMPLETED;+                }+                return IGNORE_KEYPRESS;+        }++        return NO_REMAP;+}+Index: backends/platform/ipod/sdl.h===================================================================--- backends/platform/ipod/sdl.h	(revision 0)+++ backends/platform/ipod/sdl.h	(revision 0)@@ -0,0 +1,419 @@+/* 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: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/sdl.h $+ * $Id: sdl.h 35062 2008-11-14 22:08:10Z lordhoto $+ *+ */++#ifndef SDL_COMMON_H+#define SDL_COMMON_H++#include <SDL.h>++#include "common/scummsys.h"+#include "common/system.h"+#include "graphics/scaler.h"++enum { GFX_NORMAL, GFX_HALF }; ++namespace Audio {+	class MixerImpl;+}++// Uncomment this to enable the 'on screen display' code.+#define USE_OSD	1+//#define USE_COP 1++enum remapKeyResult { NO_REMAP, EVENT_COMPLETED, IGNORE_KEYPRESS };++class OSystem_IPOD : public OSystem {+public:+	OSystem_IPOD();+	virtual ~OSystem_IPOD();++	virtual void initBackend();++	void beginGFXTransaction(void);+	TransactionError endGFXTransaction(void);++	// Set the size of the video bitmap.+	// Typically, 320x200+	virtual void initSize(uint w, uint h); // overloaded by CE backend++	virtual int getScreenChangeID() const { return _screenChangeCount; }++	// Set colors of the palette+	void setPalette(const byte *colors, uint start, uint num);++	// Get colors of the palette+	void grabPalette(byte *colors, uint start, uint num);++	// Draw a bitmap to screen.+	// The screen will not be updated to reflect the new bitmap+	virtual void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)++	virtual Graphics::Surface *lockScreen();+	virtual void unlockScreen();++	// Update the dirty areas of the screen+	void updateScreen();+	void internUpdateScreen_Real();++	// Either show or hide the mouse cursor+	bool showMouse(bool visible);++	// Warp the mouse cursor. Where set_mouse_pos() only informs the+	// backend of the mouse cursor's current position, this function+	// actually moves the cursor to the specified position.+	virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME)++	// Set the bitmap that's used when drawing the cursor.+	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale); // overloaded by CE backend (FIXME)++	// Set colors of cursor palette+	void setCursorPalette(const byte *colors, uint start, uint num);++	// Disables or enables cursor palette+	void disableCursorPalette(bool disable) {+		_cursorPaletteDisabled = disable;+		blitCursor();+	}++	// Shaking is used in SCUMM. Set current shake position.+	void setShakePos(int shake_pos);++	// Get the number of milliseconds since the program was started.+	uint32 getMillis();++	// Delay for a specified amount of milliseconds+	void delayMillis(uint msecs);++	// Get the next event.+	// Returns true if an event was retrieved.+	virtual bool pollEvent(Common::Event &event); // overloaded by CE backend++	// Set function that generates samples+	virtual void setupMixer();+	static void mixCallback(void *s, byte *samples, int len);++	virtual void closeMixer();++	virtual Audio::Mixer *getMixer();++	// Poll CD status+	// Returns true if cd audio is playing+	bool pollCD();++	// Play CD audio track+	void playCD(int track, int num_loops, int start_frame, int duration);++	// Stop CD audio track+	void stopCD();++	// Update CD audio status+	void updateCD();++	// Quit+	virtual void quit(); // overloaded by CE backend++	virtual void getTimeAndDate(struct tm &t) const;+	virtual Common::TimerManager *getTimerManager();++	// Mutex handling+	MutexRef createMutex();+	void lockMutex(MutexRef mutex);+	void unlockMutex(MutexRef mutex);+	void deleteMutex(MutexRef mutex);++	// Overlay+	virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }+	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 getHeight();+	virtual int16 getWidth();+	virtual int16 getOverlayHeight()  { return _videoMode.overlayHeight; }+	virtual int16 getOverlayWidth()   { return _videoMode.overlayWidth; }++	virtual const GraphicsMode *getSupportedGraphicsModes() const;+	virtual int getDefaultGraphicsMode() const;+	virtual bool setGraphicsMode(int mode);+	virtual int getGraphicsMode() const;++	virtual void setWindowCaption(const char *caption);+	virtual bool openCD(int drive);++	virtual bool hasFeature(Feature f);+	virtual void setFeatureState(Feature f, bool enable);+	virtual bool getFeatureState(Feature f);++#ifdef USE_OSD+	void displayMessageOnOSD(const char *msg);+#endif++	virtual Common::SaveFileManager *getSavefileManager();+	virtual FilesystemFactory *getFilesystemFactory();+	virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);++	virtual Common::SeekableReadStream *openConfigFileForReading();+	virtual Common::WriteStream *openConfigFileForWriting();++protected:+	bool _inited;++#ifdef USE_OSD+	SDL_Surface *_osdSurface;+	Uint8 _osdAlpha;			// Transparency level of the OSD+	uint32 _osdFadeStartTime;	// When to start the fade out+	enum {+		kOSDFadeOutDelay = 2 * 1000,	// Delay before the OSD is faded out (in milliseconds)+		kOSDFadeOutDuration = 500,		// Duration of the OSD fade out (in milliseconds)+		kOSDColorKey = 1,+		kOSDInitialAlpha = 80			// Initial alpha level, in percent+	};+#endif++	// hardware screen+	SDL_Surface *_hwscreen;++	// unseen game screen+	SDL_Surface *_screen;++	// temporary screen (for scalers)+	SDL_Surface *_tmpscreen;+	SDL_Surface *_tmpscreen2;++	// overlay+	SDL_Surface *_overlayscreen;+	bool _overlayVisible;+	Graphics::PixelFormat _overlayFormat;++	// Audio+	int _samplesPerSec;++	// CD Audio+	SDL_CD *_cdrom;+	int _cdTrack, _cdNumLoops, _cdStartFrame, _cdDuration;+	uint32 _cdEndTime, _cdStopTime;++	enum {+		DF_WANT_RECT_OPTIM			= 1 << 0+	};++	enum {+		kTransactionNone = 0,+		kTransactionActive = 1,+		kTransactionRollback = 2+	};++	struct TransactionDetails {+		bool sizeChanged;+		bool needHotswap;+		bool needUpdatescreen;+		bool normal1xScaler;+	};+	TransactionDetails _transactionDetails;++	struct VideoState {+		bool setup;++		bool fullscreen;+		bool aspectRatio;++		int mode;+		double scaleFactor;++		int screenWidth, screenHeight;+		int overlayWidth, overlayHeight;+	};+	VideoState _videoMode, _oldVideoMode;++	void setGraphicsModeIntern();++	/** Force full redraw on next updateScreen */+	bool _forceFull;+	ScalerProc *_scalerProc;+	//int _scalerType;+	int _transactionMode;++	bool _screenIsLocked;+	Graphics::Surface _framebuffer;++	/** Current video mode flags (see DF_* constants) */+	uint32 _modeFlags;+	bool _modeChanged;+	int _screenChangeCount;++	enum {+		NUM_DIRTY_RECT = 100,+		MAX_SCALING = 3+	};++	// Dirty rect management+	SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];+	int _numDirtyRects;+	uint32 *_dirtyChecksums;+	bool _cksumValid;+	int _cksumNum;++	// Keyboard mouse emulation.  Disabled by fingolfin 2004-12-18.+	// I am keeping the rest of the code in for now, since the joystick+	// code (or rather, "hack") uses it, too.+	struct KbdMouse {+		int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count;+		uint32 last_time, delay_time, x_down_time, y_down_time;+	};++	struct MousePos {+		// The mouse position, using either virtual (game) or real+		// (overlay) coordinates.+		int16 x, y;++		// The size and hotspot of the original cursor image.+		int16 w, h;+		int16 hotX, hotY;++		// The size and hotspot of the pre-scaled cursor image, in real+		// coordinates.+		int16 rW, rH;+		int16 rHotX, rHotY;++		// The size and hotspot of the pre-scaled cursor image, in game+		// coordinates.+		int16 vW, vH;+		int16 vHotX, vHotY;++		MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),+		             rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),+		             vHotX(0), vHotY(0)+			{ }+	};++	// mouse+	KbdMouse _km;+	bool _mouseVisible;+	bool _mouseDrawn;+	byte *_mouseData;+	SDL_Rect _mouseBackup;+	MousePos _mouseCurState;+	byte _mouseKeyColor;+	int _cursorTargetScale;+	bool _cursorPaletteDisabled;+	SDL_Surface *_mouseOrigSurface;+	SDL_Surface *_mouseSurface;+	enum {+		kMouseColorKey = 1+	};++	// joystick+	SDL_Joystick *_joystick;++	// Shake mode+	int _currentShakePos;+	int _newShakePos;++	// Palette data+	SDL_Color *_currentPalette;+	uint _paletteDirtyStart, _paletteDirtyEnd;++	// Cursor palette data+	SDL_Color *_cursorPalette;++	/**+	 * Mutex which prevents multiple threads from interfering with each other+	 * when accessing the screen.+	 */+	MutexRef _graphicsMutex;++#ifdef MIXER_DOUBLE_BUFFERING+	SDL_mutex *_soundMutex;+	SDL_cond *_soundCond;+	SDL_Thread *_soundThread;+	bool _soundThreadIsRunning;+	bool _soundThreadShouldQuit;+	+	byte _activeSoundBuf;+	uint _soundBufSize;+	byte *_soundBuffers[2];++	void mixerProducerThread();+	static int SDLCALL mixerProducerThreadEntry(void *arg);+	void initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize);+	void deinitThreadedMixer();+#endif++	FilesystemFactory *_fsFactory;+	Common::SaveFileManager *_savefile;+	Audio::MixerImpl *_mixer;++	SDL_TimerID _timerID;+	Common::TimerManager *_timer;++	int _rotation_modulation;+	int _hwScreenOffsetX;+	int _hwScreenOffsetY;++protected:+	void addDirtyRgnAuto(const byte *buf);+	void makeChecksums(const byte *buf);++	virtual void addDirtyRect(int x, int y, int w, int h, bool realCoordinates = false); // overloaded by CE backend++	virtual void drawMouse(); // overloaded by CE backend+	virtual void undrawMouse(); // overloaded by CE backend (FIXME)+	virtual void blitCursor(); // overloaded by CE backend (FIXME)++	/** Set the position of the virtual mouse cursor. */+	void setMousePos(int x, int y);+	virtual void fillMouseEvent(Common::Event &event, int x, int y); // overloaded by CE backend+	void toggleMouseGrab();++	virtual bool loadGFXMode(); // overloaded by CE backend+	virtual void unloadGFXMode(); // overloaded by CE backend+	virtual bool hotswapGFXMode(); // overloaded by CE backend+	virtual void internUpdateScreen(); // overloaded by CE backend++	void setFullscreenMode(bool enable);+	void setAspectRatioCorrection(bool enable);++	virtual bool saveScreenshot(const char *filename); // overloaded by CE backend++	int effectiveScreenHeight() const {+		return (_videoMode.aspectRatio ? real2Aspect(_videoMode.screenHeight) : _videoMode.screenHeight)+			* _videoMode.scaleFactor;+	}++	void handleKbdMouse();++	virtual remapKeyResult remapKey(SDL_Event &ev, Common::Event &event);++};++#ifdef USE_COP+	void ipod_init_cop(OSystem_IPOD *ipod_g_system);+	void ipod_cop_update_screen();+#endif++void Scaleo5x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height);++#endifIndex: backends/platform/ipod/module.mk===================================================================--- backends/platform/ipod/module.mk	(revision 0)+++ backends/platform/ipod/module.mk	(revision 0)@@ -0,0 +1,14 @@+MODULE := backends/platform/ipod++MODULE_OBJS := \+	events.o \+	graphics.o \+	main.o \+	sdl.o \+	cop.o++MODULE_DIRS += \+	backends/platform/ipod/++# We don't use the rules.mk here on purpose+OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)Index: base/commandLine.cpp===================================================================--- base/commandLine.cpp	(revision 35535)+++ base/commandLine.cpp	(working copy)@@ -137,7 +137,7 @@ 	vsnprintf(buf, STRINGBUFLEN, s, va); 	va_end(va); -#if !(defined(__GP32__) || defined (__SYMBIAN32__))+#if !(defined(__GP32__) || defined (__SYMBIAN32__) || defined (IPOD)) 	printf(USAGE_STRING, s_appName, buf, s_appName, s_appName); #endif 	exit(1);