aboutsummaryrefslogtreecommitdiff
path: root/backends
diff options
context:
space:
mode:
Diffstat (limited to 'backends')
-rw-r--r--backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp590
-rw-r--r--backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h53
-rw-r--r--backends/module.mk5
-rw-r--r--backends/platform/sdl/module.mk6
-rw-r--r--backends/platform/sdl/posix/posix-main.cpp2
-rw-r--r--backends/platform/sdl/raspberrypi/README.RASPBERRYPI106
-rw-r--r--backends/platform/sdl/raspberrypi/raspberrypi-main.cpp51
-rw-r--r--backends/platform/sdl/raspberrypi/raspberrypi.cpp42
-rw-r--r--backends/platform/sdl/raspberrypi/raspberrypi.h35
-rw-r--r--backends/platform/sdl/win32/win32-main.cpp5
-rw-r--r--backends/platform/symbian/mmp/config.mmh13
-rw-r--r--backends/platform/symbian/mmp/scummvm_avalanche.mmp.in1
-rw-r--r--backends/platform/symbian/mmp/scummvm_cge2.mmp.in1
-rw-r--r--backends/platform/symbian/mmp/scummvm_tsage.mmp.in1
-rw-r--r--backends/platform/symbian/src/SymbianOS.cpp4
-rw-r--r--backends/platform/symbian/src/portdefs.h8
-rw-r--r--backends/saves/default/default-saves.cpp5
17 files changed, 906 insertions, 22 deletions
diff --git a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp
new file mode 100644
index 0000000000..3da536be2b
--- /dev/null
+++ b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.cpp
@@ -0,0 +1,590 @@
+/* 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.
+ *
+ */
+
+// Needed for Raspberry Pi header inclusion
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "common/scummsys.h"
+
+#if defined(DISPMANX)
+
+#include "backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h"
+#include "graphics/scaler/aspect.h"
+#include "common/mutex.h"
+#include "common/textconsole.h"
+
+#include <bcm_host.h>
+
+struct dispvarsStruct {
+ DISPMANX_DISPLAY_HANDLE_T display;
+ DISPMANX_UPDATE_HANDLE_T update;
+ DISPMANX_ELEMENT_HANDLE_T element;
+ VC_IMAGE_TYPE_T pixFormat;
+ VC_DISPMANX_ALPHA_T alpha;
+
+ VC_RECT_T bmpRect;
+ VC_RECT_T srcRect;
+ VC_RECT_T dstRect;
+ uint32_t vcImagePtr;
+ int screen;
+ int pitch;
+ unsigned int dispmanxWidth;
+ unsigned int dispmanxHeight;
+ bool aspectRatioCorrection;
+ void *pixmem;
+
+ int numpages;
+ dispmanxPage *pages;
+ dispmanxPage *currentPage;
+ int pageflipPending;
+
+ pthread_cond_t vsyncCondition;
+ pthread_mutex_t vsyncCondMutex;
+ pthread_mutex_t pendingMutex;
+
+ SDL_Surface *fscreen;
+};
+
+struct dispmanxPage {
+ DISPMANX_RESOURCE_HANDLE_T resource;
+ bool used;
+ // Each page has it's own mutex for
+ // isolating the access to it's "used" flag.
+ pthread_mutex_t pageUsedMutex;
+
+ // This field will allow us to access the
+ // main dispvars struct, for the vsync cb.
+ struct dispvarsStruct *dispvars;
+};
+
+DispmanXSdlGraphicsManager::DispmanXSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window)
+ : SurfaceSdlGraphicsManager(sdlEventSource, window) {
+ _dispvars = new(dispvarsStruct);
+ dispmanXInit();
+}
+
+DispmanXSdlGraphicsManager::~DispmanXSdlGraphicsManager() {
+ dispmanXVideoQuit();
+ delete(_dispvars);
+}
+
+void DispmanXSdlGraphicsManager::dispmanXInit() {
+ _dispvars->screen = 0;
+ _dispvars->vcImagePtr = 0;
+ _dispvars->numpages = 3;
+ _dispvars->pages = (struct dispmanxPage *)calloc(_dispvars->numpages, sizeof(struct dispmanxPage));
+ _dispvars->pageflipPending = 0;
+ _dispvars->currentPage = NULL;
+ _dispvars->pixFormat = VC_IMAGE_RGB565;
+
+ /* Transparency disabled */
+ _dispvars->alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
+ _dispvars->alpha.opacity = 255;
+ _dispvars->alpha.mask = 0;
+ _dispvars->element = 0;
+
+ // Init each page's variables
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ _dispvars->pages[i].used = false;
+ _dispvars->pages[i].dispvars = _dispvars;
+ _dispvars->pages[i].resource = 0;
+ pthread_mutex_init(&_dispvars->pages[i].pageUsedMutex, NULL);
+ }
+
+ // Initialize the other mutex and condition variables
+ pthread_cond_init(&_dispvars->vsyncCondition, NULL);
+ pthread_mutex_init(&_dispvars->pendingMutex, NULL);
+ pthread_mutex_init(&_dispvars->vsyncCondMutex, NULL);
+
+ // Before we call any vc_* function, we need to call this one.
+ bcm_host_init();
+
+ _dispvars->display = vc_dispmanx_display_open(_dispvars->screen);
+ graphics_get_display_size(_dispvars->display, &_dispvars->dispmanxWidth, &_dispvars->dispmanxHeight);
+
+ // We need this so SDL_SetVideoMode() is called once.
+ _dispvars->fscreen = NULL;
+}
+
+void DispmanXSdlGraphicsManager::dispmanXSetup(int srcWidth, int srcHeight) {
+ unsigned int dstWidth, dstHeight, dstXpos, dstYpos;
+
+ // If we have an element, we have to free it along with it's resources.
+ if (_dispvars->element) {
+ dispmanXFreeResources();
+ }
+
+ // We do this for 2 bytes per pixel which is default on the Rpi.
+ _dispvars->pitch = srcWidth * 2;
+ if (_dispvars->aspectRatioCorrection) {
+ float aspect = ((float)srcWidth / (float)srcHeight);
+ dstWidth = _dispvars->dispmanxHeight * aspect;
+ } else {
+ dstWidth = _dispvars->dispmanxWidth;
+ }
+ dstHeight = _dispvars->dispmanxHeight;
+
+ // If we obtain a scaled image width that is bigger than the physical screen width,
+ // then we keep the physical screen width as our maximun width.
+ if (dstWidth > _dispvars->dispmanxWidth) {
+ dstWidth = _dispvars->dispmanxWidth;
+ }
+
+ dstXpos = (_dispvars->dispmanxWidth - dstWidth) / 2;
+ dstYpos = (_dispvars->dispmanxHeight - dstHeight) / 2;
+
+ // Remember we have to transfer the whole bitmap even if we would have
+ // interest in a part of it! Blitting is done by the GPU.
+ vc_dispmanx_rect_set(&_dispvars->dstRect, dstXpos, dstYpos, dstWidth, dstHeight);
+ vc_dispmanx_rect_set(&_dispvars->bmpRect, 0, 0, srcWidth, srcHeight);
+ vc_dispmanx_rect_set(&_dispvars->srcRect, 0, 0, srcWidth << 16, srcHeight << 16);
+
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ _dispvars->pages[i].resource = vc_dispmanx_resource_create(_dispvars->pixFormat,
+ srcWidth, srcHeight, &(_dispvars->vcImagePtr));
+ }
+
+ // Add the element. Has to be removed before getting here again.
+ _dispvars->update = vc_dispmanx_update_start(0);
+
+ _dispvars->element = vc_dispmanx_element_add(
+ _dispvars->update,_dispvars->display, 0,
+ &_dispvars->dstRect, 0,
+ &_dispvars->srcRect, DISPMANX_PROTECTION_NONE,
+ &_dispvars->alpha, 0, (DISPMANX_TRANSFORM_T)0);
+
+ vc_dispmanx_update_submit_sync(_dispvars->update);
+}
+
+void dispmanXVSyncCallback(DISPMANX_UPDATE_HANDLE_T u, void *arg) {
+ struct dispmanxPage *page = (struct dispmanxPage*)arg;
+ struct dispvarsStruct *dispvars = page->dispvars;
+
+ // Marking the page as free must be done before the signaling
+ // so when the update function continues (it won't continue until we signal)
+ // we can chose this page as free.
+ if (dispvars->currentPage) {
+ pthread_mutex_lock(&dispvars->currentPage->pageUsedMutex);
+
+ // We mark as free the page that was visible until now.
+ page->dispvars->currentPage->used = false;
+
+ pthread_mutex_unlock(&dispvars->currentPage->pageUsedMutex);
+ }
+
+ // The page on which we issued the flip that
+ // caused this callback becomes the visible one
+ dispvars->currentPage = page;
+
+ // These two things must be isolated "atomically" to avoid getting
+ // a false positive in the pending_mutex test in update function.
+ pthread_mutex_lock(&dispvars->pendingMutex);
+
+ dispvars->pageflipPending--;
+ pthread_cond_signal(&dispvars->vsyncCondition);
+
+ pthread_mutex_unlock(&dispvars->pendingMutex);
+}
+
+void DispmanXSdlGraphicsManager::dispmanXUpdate() {
+ // Wait until last issued flip completes to get a free page. Also,
+ // dispmanx doesn't support issuing more than one pageflip.
+ pthread_mutex_lock(&_dispvars->pendingMutex);
+
+ if (_dispvars->pageflipPending > 0) {
+ pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->pendingMutex);
+ }
+
+ pthread_mutex_unlock(&_dispvars->pendingMutex);
+
+ struct dispmanxPage *page = dispmanXGetFreePage();
+
+ // Frame blitting
+ vc_dispmanx_resource_write_data(page->resource, _dispvars->pixFormat,
+ _dispvars->pitch, _dispvars->pixmem, &_dispvars->bmpRect);
+
+ // Issue a page flip at the next vblank interval (will be done at vsync anyway).
+ _dispvars->update = vc_dispmanx_update_start(0);
+
+ vc_dispmanx_element_change_source(_dispvars->update, _dispvars->element,
+ page->resource);
+ vc_dispmanx_update_submit(_dispvars->update, &dispmanXVSyncCallback, page);
+
+ pthread_mutex_lock(&_dispvars->pendingMutex);
+ _dispvars->pageflipPending++;
+ pthread_mutex_unlock(&_dispvars->pendingMutex);
+}
+
+struct dispmanxPage *DispmanXSdlGraphicsManager::dispmanXGetFreePage(void) {
+ struct dispmanxPage *page = NULL;
+
+ while (!page) {
+ // Try to find a free page
+ for (int i = 0; i < _dispvars->numpages; ++i) {
+ if (!_dispvars->pages[i].used) {
+ page = (_dispvars->pages) + i;
+ break;
+ }
+ }
+
+ // If no page is free at the moment,
+ // wait until a free page is freed by vsync CB.
+ if (!page) {
+ pthread_mutex_lock(&_dispvars->vsyncCondMutex);
+ pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->vsyncCondMutex);
+ pthread_mutex_unlock(&_dispvars->vsyncCondMutex);
+ }
+ }
+
+ // We mark the choosen page as used
+ pthread_mutex_lock(&page->pageUsedMutex);
+ page->used = true;
+ pthread_mutex_unlock(&page->pageUsedMutex);
+
+ return page;
+}
+
+void DispmanXSdlGraphicsManager::dispmanXFreeResources(void) {
+ // What if we run into the vsync cb code after freeing the resources?
+ pthread_mutex_lock(&_dispvars->pendingMutex);
+ if (_dispvars->pageflipPending > 0)
+ {
+ pthread_cond_wait(&_dispvars->vsyncCondition, &_dispvars->pendingMutex);
+ }
+ pthread_mutex_unlock(&_dispvars->pendingMutex);
+
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ vc_dispmanx_resource_delete(_dispvars->pages[i].resource);
+ _dispvars->pages[i].resource = 0;
+ _dispvars->pages[i].used = false;
+ }
+
+ _dispvars->update = vc_dispmanx_update_start(0);
+ vc_dispmanx_element_remove(_dispvars->update, _dispvars->element);
+ vc_dispmanx_update_submit_sync(_dispvars->update);
+ // We use this on the setup function to know if we have to free resources and element.
+ _dispvars->element = 0;
+}
+
+void DispmanXSdlGraphicsManager::dispmanXVideoQuit() {
+ // This also waits for pending flips to complete, that's needed before
+ // we destroy the mutexes and condition.
+ dispmanXFreeResources();
+
+ // Destroy the mutexes and conditions
+ for (int i = 0; i < _dispvars->numpages; i++) {
+ pthread_mutex_destroy(&_dispvars->pages[i].pageUsedMutex);
+ }
+ pthread_mutex_destroy(&_dispvars->pendingMutex);
+ pthread_mutex_destroy(&_dispvars->vsyncCondMutex);
+ pthread_cond_destroy(&_dispvars->vsyncCondition);
+
+ free(_dispvars->pages);
+
+ // Close display and deinit
+ vc_dispmanx_display_close(_dispvars->display);
+ bcm_host_deinit();
+}
+
+bool DispmanXSdlGraphicsManager::loadGFXMode() {
+ _forceFull = true;
+
+ // In dispmanX, we manage aspect ratio correction, so for scummvm it's always disabled.
+ _videoMode.aspectRatioCorrection = false;
+
+ _videoMode.overlayWidth = _videoMode.screenWidth;
+ _videoMode.overlayHeight = _videoMode.screenHeight;
+ _videoMode.hardwareWidth = _videoMode.screenWidth;
+ _videoMode.hardwareHeight = _videoMode.screenHeight;
+
+ //
+ // Create the surface that contains the 8 bit game data
+ //
+
+ _screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth, _videoMode.screenHeight,
+ _screenFormat.bytesPerPixel << 3,
+ ((1 << _screenFormat.rBits()) - 1) << _screenFormat.rShift ,
+ ((1 << _screenFormat.gBits()) - 1) << _screenFormat.gShift ,
+ ((1 << _screenFormat.bBits()) - 1) << _screenFormat.bShift ,
+ ((1 << _screenFormat.aBits()) - 1) << _screenFormat.aShift );
+ if (_screen == NULL)
+ error("allocating _screen failed");
+
+ // Avoid having SDL_SRCALPHA set even if we supplied an alpha-channel in the format.
+ SDL_SetAlpha(_screen, 0, 255);
+
+ // We set our own default palette to all black.
+ SDL_SetColors(_screen, _currentPalette, 0, 256);
+
+ //
+ // Create the surface that contains the scaled graphics in 16 bit mode
+ //
+
+ dispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight);
+
+ _hwscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.hardwareWidth, _videoMode.hardwareHeight, 16,
+ 0, 0, 0, 0);
+
+ // This is just so SDL 1.x input is initialized. Only once!
+ if (_dispvars->fscreen == NULL)
+ _dispvars->fscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 16, SDL_FULLSCREEN);
+ if (_hwscreen == NULL) {
+ // Don't use error here because we don't have access to the debug console
+ warning("Allocating surface for dispmanX rendering _hwscreen failed");
+ g_system->quit();
+ }
+
+ // We render to dispmanx resources from _hwscreen pixels array
+ _dispvars->pixmem = _hwscreen->pixels;
+
+ _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;
+
+#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
+
+ _eventSource->resetKeyboadEmulation(
+ _videoMode.screenWidth, effectiveScreenHeight());
+
+ return true;
+}
+
+void DispmanXSdlGraphicsManager::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 = 0;
+ src.w = dst.w = _videoMode.screenWidth;
+ src.h = dst.h = _videoMode.screenHeight;
+ if (SDL_BlitSurface(_screen, &src, _hwscreen, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+ SDL_LockSurface(_hwscreen);
+ SDL_LockSurface(_overlayscreen);
+ Normal1x((byte *)(_hwscreen->pixels), _hwscreen->pitch,
+ (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);
+
+ SDL_UnlockSurface(_hwscreen);
+ SDL_UnlockSurface(_overlayscreen);
+
+ _forceFull = true;
+}
+
+void DispmanXSdlGraphicsManager::internUpdateScreen() {
+ SDL_Surface *srcSurf, *origSurf;
+ int height, width;
+
+ // If the shake position changed, fill the dirty area with blackness
+ if (_currentShakePos != _newShakePos ||
+ (_mouseNeedsRedraw && _mouseBackup.y <= _currentShakePos)) {
+ SDL_Rect blackrect = {0, 0, (Uint16)(_videoMode.screenWidth * _videoMode.scaleFactor), (Uint16)(_newShakePos * _videoMode.scaleFactor)};
+
+ if (_dispvars->aspectRatioCorrection && !_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 = _hwscreen;
+ width = _videoMode.screenWidth;
+ height = _videoMode.screenHeight;
+ } else {
+ origSurf = _overlayscreen;
+ srcSurf = _hwscreen;
+ width = _videoMode.overlayWidth;
+ height = _videoMode.overlayHeight;
+ }
+
+ // Add the area covered by the mouse cursor to the list of dirty rects if
+ // we have to redraw the mouse.
+ if (_mouseNeedsRedraw)
+ undrawMouse();
+
+ // 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;
+ }
+
+ // Only draw anything if necessary
+ if (_numDirtyRects > 0 || _mouseNeedsRedraw) {
+ SDL_Rect *r;
+ SDL_Rect dst;
+ SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;
+
+ for (r = _dirtyRectList; r != lastRect; ++r) {
+ dst = *r;
+
+ if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
+ error("SDL_BlitSurface failed: %s", SDL_GetError());
+ }
+
+ // 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 = 0;
+ _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
+ if (!_displayDisabled) {
+ SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+ dispmanXUpdate();
+ }
+ }
+
+ _numDirtyRects = 0;
+ _forceFull = false;
+ _mouseNeedsRedraw = false;
+}
+
+bool DispmanXSdlGraphicsManager::handleScalerHotkeys(Common::KeyCode key) {
+
+ // Ctrl-Alt-a toggles aspect ratio correction
+ if (key == 'a') {
+ setFeatureState(OSystem::kFeatureAspectRatioCorrection, !_dispvars->aspectRatioCorrection);
+#ifdef USE_OSD
+ char buffer[128];
+ if (_dispvars->aspectRatioCorrection)
+ sprintf(buffer, "%s", ("Enabled aspect ratio correction"));
+ else
+ sprintf(buffer, "%s", ("Disabled aspect ratio correction"));
+ displayMessageOnOSD(buffer);
+#endif
+ internUpdateScreen();
+ return true;
+ }
+
+ return true;
+}
+
+bool DispmanXSdlGraphicsManager::hasFeature(OSystem::Feature f) {
+ if (f == OSystem::kFeatureFullscreenMode) {
+ return false;
+ } else {
+ return SurfaceSdlGraphicsManager::hasFeature(f);
+ }
+}
+
+void DispmanXSdlGraphicsManager::setFullscreenMode(bool enable) {
+ // Since we're always in fullscreen mode, we do nothing here.
+}
+
+void DispmanXSdlGraphicsManager::setAspectRatioCorrection(bool enable) {
+ Common::StackLock lock(_graphicsMutex);
+ // We simply take note on what's the aspect ratio correction activation state.
+ _dispvars->aspectRatioCorrection = enable;
+
+ // If we have a videomode setup already, call dispmanXSetup() again so aspect ratio
+ // correction activation/deactivation works from the menu.
+ if (_oldVideoMode.setup && _dispvars->aspectRatioCorrection == enable) {
+ dispmanXSetup(_videoMode.screenWidth, _videoMode.screenHeight);
+ }
+}
+
+#endif
diff --git a/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h
new file mode 100644
index 0000000000..6a2ede2383
--- /dev/null
+++ b/backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef BACKENDS_GRAPHICS_SDL_DISPMANX_H
+#define BACKENDS_GRAPHICS_SDL_DISPMANX_H
+
+#include "backends/graphics/surfacesdl/surfacesdl-graphics.h"
+
+struct dispvarsStruct;
+struct dispmanxPage;
+
+class DispmanXSdlGraphicsManager : public SurfaceSdlGraphicsManager {
+public:
+ DispmanXSdlGraphicsManager(SdlEventSource *sdlEventSource, SdlWindow *window);
+ ~DispmanXSdlGraphicsManager();
+ bool loadGFXMode();
+ void internUpdateScreen();
+ bool handleScalerHotkeys(Common::KeyCode key);
+ void setFullscreenMode(bool enable);
+ void setAspectRatioCorrection(bool enable);
+ void clearOverlay();
+ bool hasFeature(OSystem::Feature f);
+protected:
+ // Raspberry Pi Dispmanx API
+ void dispmanXSetup(int width, int height);
+ void dispmanXInit();
+ void dispmanXUpdate();
+ dispmanxPage *dispmanXGetFreePage();
+ void dispmanXFreeResources();
+ void dispmanXVideoQuit();
+ dispvarsStruct *_dispvars;
+};
+
+#endif /* BACKENDS_GRAPHICS_SDL_DISPMANX_H */
diff --git a/backends/module.mk b/backends/module.mk
index e5e2905781..7f2fb05489 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -129,6 +129,11 @@ MODULE_OBJS += \
mixer/sdl13/sdl13-mixer.o
endif
+ifdef DISPMANX
+MODULE_OBJS += \
+ graphics/dispmanxsdl/dispmanxsdl-graphics.o
+endif
+
ifeq ($(BACKEND),tizen)
MODULE_OBJS += \
timer/tizen/timer.o
diff --git a/backends/platform/sdl/module.mk b/backends/platform/sdl/module.mk
index 74dd506d31..65d12dceed 100644
--- a/backends/platform/sdl/module.mk
+++ b/backends/platform/sdl/module.mk
@@ -36,6 +36,12 @@ MODULE_OBJS += \
ps3/ps3.o
endif
+ifdef DISPMANX
+MODULE_OBJS += \
+ raspberrypi/raspberrypi-main.o \
+ raspberrypi/raspberrypi.o
+endif
+
# We don't use rules.mk but rather manually update OBJS and MODULE_DIRS.
MODULE_OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS))
OBJS := $(MODULE_OBJS) $(OBJS)
diff --git a/backends/platform/sdl/posix/posix-main.cpp b/backends/platform/sdl/posix/posix-main.cpp
index d07db11b0c..492da70eeb 100644
--- a/backends/platform/sdl/posix/posix-main.cpp
+++ b/backends/platform/sdl/posix/posix-main.cpp
@@ -22,7 +22,7 @@
#include "common/scummsys.h"
-#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3)
+#if defined(POSIX) && !defined(MACOSX) && !defined(SAMSUNGTV) && !defined(MAEMO) && !defined(WEBOS) && !defined(LINUXMOTO) && !defined(GPH_DEVICE) && !defined(GP2X) && !defined(DINGUX) && !defined(OPENPANDORA) && !defined(PLAYSTATION3) && !defined(DISPMANX)
#include "backends/platform/sdl/posix/posix.h"
#include "backends/plugins/sdl/sdl-provider.h"
diff --git a/backends/platform/sdl/raspberrypi/README.RASPBERRYPI b/backends/platform/sdl/raspberrypi/README.RASPBERRYPI
new file mode 100644
index 0000000000..f8d872b519
--- /dev/null
+++ b/backends/platform/sdl/raspberrypi/README.RASPBERRYPI
@@ -0,0 +1,106 @@
+ScummVM-RASPBERRYPI README
+==============================================================================
+
+Notes
+============
+
+This version of ScummVM is specially tailored to use DispmanX, the native 2D
+API on the Raspberry Pi. The idea is that scaling and drawing on a double
+buffer with a non-blocking vsync wait is all done using the on-board VideoCore
+hardware, thus using only a small fraction of the CPU ScummVM uses when ran
+on a clunky, software-scaled and desynced X11 environment using the X11 API.
+Thus, running this version under an X11 session is not supported.
+
+Requirements
+============
+- Raspberry Pi 1 or 2 microcomputer.
+- Raspbian (Debian) installed on SD card. Other distros may be supported if
+ they include the VideoCore runtime libraries that Raspbian includes.
+-An attached keyboard and mouse, or alternatively joystick.
+
+Controls
+============
+
+The standard ScummVM keyboard and mouse controls are used as in any other
+GNU/Linux based system.
+Use the --joystick parameter if you want to use a joystick instead of the
+intended mouse for playing the games (not recommended).
+
+Installation from binaries
+==============================
+
+We have at least three methods to get the binaries into the Raspbian SD:
+
+1) Since Debian (Raspbian) includes an ssh service by default, I recommend
+keeping the SD card on the Raspberry Pi, and using scp to copy the package over
+to your home directory in the Debian filesystem.
+
+scp scummvm-rpi_<version>.zip pi@<raspberrypi_ip>:/home/pi
+
+2) If your RaspberryPi has internet access, you can simply use wget to
+download the package to your home folder:
+
+cd ~/
+wget <package_link>
+
+3) You could also connect the Raspbian SD card to your main PC and, after
+mounting it (or being automounted as it would be in most desktop GNU/Linux
+systems), copy the package file manually to your home directory.
+How to mount an SD and copy files to it is beyond the scope of this README.
+
+Once we have the package file in our home directory using one of the three
+aforementioned methods, we would need to uncompress it:
+
+unzip scummvm-rpi_<version>.zip
+
+As a result, a directory containing the scummvm along with this README will be
+created.
+We can run it by simply changing to our scummvm directory and executing the
+scummvm file.
+
+cd scummvm-rpi
+./scummvm
+
+I recommend copying the games to /home/pi/scummvm-rpi. Adding the games via the menu
+works as in any other system ScummVM runs on.
+
+Building from sources
+==============================
+
+We have two options to build once we have the sources in our main GNU/Linux desktop
+class PC or in our Raspberry Pi:
+
+1) Building on the Raspberry Pi itself, although possible, is an SLOW task for the
+little computer unless you use distributed gcc (or distcc for short).
+
+Local compilation would simply consist of the "standard" GNU/Linux building process:
+
+cd <sources_dir>
+
+./configure --enable-dispmanx -disable-debug --enable-release
+--enable-optimizations --disable-mt32emu --disable-flac --disable-mad --disable-vorbis
+--disable-tremor --disable-fluidsynth --disable-taskbar --disable-timidity --disable-alsa
+--disable-scalers --disable-hq-scalers --disable-savegame-timestamp --disable-eventrecorder
+
+make
+
+As you can see, we're manually disabling scalers because we prefer dispmanx for that, which
+makes scalers unnecessary on a CPU limited platform like this, timestamps because most people
+doesn't have an RTC on the Raspberry Pi, and event recorder to save SD card write cycles.
+All these are automatically disabled when we crosscompile by passing "--host=raspberrypi",
+which is not the case.
+
+¡¡It will be an SLOW process, taking several hours to complete, unless you
+are running distcc against a fast compilation server!!
+
+2) If we want to build by cross-compiling on a GNU/Linux X86-based computer,
+we can find concise instructions for this can be found on the ScummVM wiki:
+
+http://wiki.scummvm.org/index.php/Compiling_ScummVM/RPI
+
+NOTE: Distcc is my preferred method as it does cross-compiling totally transparent
+(we build ON the Pi but the actual CPU-intensive compilation is made on an external
+server), but it involves building a custom gcc version on the compilation server and
+configuring a server and client in both the Raspberry Pi and the server.
+
+Enjoy!
diff --git a/backends/platform/sdl/raspberrypi/raspberrypi-main.cpp b/backends/platform/sdl/raspberrypi/raspberrypi-main.cpp
new file mode 100644
index 0000000000..cddbcb7ec4
--- /dev/null
+++ b/backends/platform/sdl/raspberrypi/raspberrypi-main.cpp
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "backends/platform/sdl/raspberrypi/raspberrypi.h"
+#include "backends/plugins/sdl/sdl-provider.h"
+#include "common/scummsys.h"
+#include "base/main.h"
+
+#if defined(DISPMANX)
+int main(int argc, char* argv[]) {
+
+ // Create our OSystem instance
+ g_system = new OSystem_SDL_RaspberryPi();
+ assert(g_system);
+
+ // Pre initialize the backend
+ ((OSystem_SDL_RaspberryPi *)g_system)->init();
+
+#ifdef DYNAMIC_MODULES
+ PluginManager::instance().addPluginProvider(new SDLPluginProvider());
+#endif
+
+ // Invoke the actual ScummVM main entry point:
+ int res = scummvm_main(argc, argv);
+
+ // Free OSystem
+ delete (OSystem_SDL_RaspberryPi *)g_system;
+
+ return res;
+}
+
+#endif
diff --git a/backends/platform/sdl/raspberrypi/raspberrypi.cpp b/backends/platform/sdl/raspberrypi/raspberrypi.cpp
new file mode 100644
index 0000000000..206203d82e
--- /dev/null
+++ b/backends/platform/sdl/raspberrypi/raspberrypi.cpp
@@ -0,0 +1,42 @@
+/* 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.
+ *
+ */
+
+#if defined(DISPMANX)
+
+#include "backends/platform/sdl/raspberrypi/raspberrypi.h"
+#include "backends/graphics/dispmanxsdl/dispmanxsdl-graphics.h"
+
+void OSystem_SDL_RaspberryPi::initBackend() {
+ // Create the events manager
+ if (_eventSource == 0)
+ _eventSource = new SdlEventSource();
+
+ // Create the graphics manager
+ if (_graphicsManager == 0) {
+ _graphicsManager = new DispmanXSdlGraphicsManager(_eventSource, _window);
+ }
+
+ // Call parent implementation of this method
+ OSystem_POSIX::initBackend();
+}
+
+#endif
diff --git a/backends/platform/sdl/raspberrypi/raspberrypi.h b/backends/platform/sdl/raspberrypi/raspberrypi.h
new file mode 100644
index 0000000000..45e2c505f6
--- /dev/null
+++ b/backends/platform/sdl/raspberrypi/raspberrypi.h
@@ -0,0 +1,35 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef SDL_DISPMANX_COMMON_H
+#define SDL_DISPMANX_COMMON_H
+
+#if defined(DISPMANX)
+#include "backends/platform/sdl/posix/posix.h"
+
+class OSystem_SDL_RaspberryPi : public OSystem_POSIX {
+public:
+ void initBackend();
+};
+
+#endif /* DISPMANX */
+#endif /* SDL_DISPMANX_COMMON_H */
diff --git a/backends/platform/sdl/win32/win32-main.cpp b/backends/platform/sdl/win32/win32-main.cpp
index c6c15c00e8..c6339f0c8c 100644
--- a/backends/platform/sdl/win32/win32-main.cpp
+++ b/backends/platform/sdl/win32/win32-main.cpp
@@ -43,7 +43,12 @@ int __stdcall WinMain(HINSTANCE /*hInst*/, HINSTANCE /*hPrevInst*/, LPSTR /*lpC
#if !SDL_VERSION_ATLEAST(2, 0, 0)
SDL_SetModuleHandle(GetModuleHandle(NULL));
#endif
+// HACK: __argc, __argv are broken and return zero when using mingwrt 4.0+ on MinGW
+#if defined(__GNUC__) && defined(__MINGW32__) && !defined(__MINGW64__)
+ return main(_argc, _argv);
+#else
return main(__argc, __argv);
+#endif
}
int main(int argc, char *argv[]) {
diff --git a/backends/platform/symbian/mmp/config.mmh b/backends/platform/symbian/mmp/config.mmh
index f397e5ec64..da91117cf6 100644
--- a/backends/platform/symbian/mmp/config.mmh
+++ b/backends/platform/symbian/mmp/config.mmh
@@ -29,19 +29,6 @@
// Common EPOC MMP makefiles option storage for ScummVM
//
-/*
- * MACRO REMOVE_UNDEFINED used for bypass this bug -
- * http://sourceforge.net/p/scummvm/bugs/6437/
- * Requre change in epoc32\include\libc\sys\unistd.h by
- *
- * #ifndef REMOVE_UNDEFINED
- * #define remove(x) unlink(x)
- * #define wremove(x) wunlink(x)
- * #endif //REMOVE_UNDEFINED
- *
- * Affects Avalanche, CGE2 and Tsage
- */
-
// *** Definitions
OPTION MSVC /QIfist /Ob1 /Oy /GF // /QIfist disables use of __ftol2 to avoid linker probs with MS libc: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/vcrefQIfistSuppress_ftol.asp
diff --git a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
index 49c73222ca..6d44c66bf7 100644
--- a/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_avalanche.mmp.in
@@ -33,7 +33,6 @@
TARGET scummvm_avalanche.lib
TARGETTYPE lib
-MACRO REMOVE_UNDEFINED
#include "config.mmh"
//START_AUTO_MACROS_SLAVE//
diff --git a/backends/platform/symbian/mmp/scummvm_cge2.mmp.in b/backends/platform/symbian/mmp/scummvm_cge2.mmp.in
index 1561b0f479..7c78f47bfd 100644
--- a/backends/platform/symbian/mmp/scummvm_cge2.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_cge2.mmp.in
@@ -32,7 +32,6 @@
TARGET scummvm_cge2.lib
TARGETTYPE lib
-MACRO REMOVE_UNDEFINED
#include "config.mmh"
//START_AUTO_MACROS_SLAVE//
diff --git a/backends/platform/symbian/mmp/scummvm_tsage.mmp.in b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in
index 93f278e279..6b57827e1e 100644
--- a/backends/platform/symbian/mmp/scummvm_tsage.mmp.in
+++ b/backends/platform/symbian/mmp/scummvm_tsage.mmp.in
@@ -32,7 +32,6 @@
TARGET scummvm_tsage.lib
TARGETTYPE lib
-MACRO REMOVE_UNDEFINED
#include "config.mmh"
//START_AUTO_MACROS_SLAVE//
diff --git a/backends/platform/symbian/src/SymbianOS.cpp b/backends/platform/symbian/src/SymbianOS.cpp
index e28b78900c..4d417b5a66 100644
--- a/backends/platform/symbian/src/SymbianOS.cpp
+++ b/backends/platform/symbian/src/SymbianOS.cpp
@@ -197,7 +197,3 @@ void* scumm_bsearch(const void *key, const void *base, size_t nmemb, size_t size
return NULL;
}
-int remove(const char *path)
-{
- return unlink(path);
-}
diff --git a/backends/platform/symbian/src/portdefs.h b/backends/platform/symbian/src/portdefs.h
index 1fb941963b..f9da09d3eb 100644
--- a/backends/platform/symbian/src/portdefs.h
+++ b/backends/platform/symbian/src/portdefs.h
@@ -58,11 +58,17 @@ typedef signed long int int32;
// re-define those data types.
#define SCUMMVM_DONT_DEFINE_TYPES
+// Hide the macro "remove" defined in unistd.h from anywere except where
+// we explicitly require it. This lets us use the name "remove" in engines.
+// Must be after including unistd.h .
+#ifndef SYMBIAN_USE_SYSTEM_REMOVE
+#undef remove
+#endif
+
#define SMALL_SCREEN_DEVICE
#define DISABLE_COMMAND_LINE
#define USE_RGB_COLOR
-int remove(const char *path);
#if defined(USE_TREMOR) && !defined(USE_VORBIS)
#define USE_VORBIS // make sure this one is defined together with USE_TREMOR!
diff --git a/backends/saves/default/default-saves.cpp b/backends/saves/default/default-saves.cpp
index 1b955a5021..4f7013724a 100644
--- a/backends/saves/default/default-saves.cpp
+++ b/backends/saves/default/default-saves.cpp
@@ -20,6 +20,11 @@
*
*/
+// This define lets us use the system function remove() on Symbian, which
+// is disabled by default due to a macro conflict.
+// See backends/platform/symbian/src/portdefs.h .
+#define SYMBIAN_USE_SYSTEM_REMOVE
+
#include "common/scummsys.h"
#if !defined(DISABLE_DEFAULT_SAVEFILEMANAGER)