rendered paste bodyIndex: 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);