[Scummvm-cvs-logs] SF.net SVN: scummvm:[39991] scummvm/branches/branch-0-13-0/backends/ platform/gp2x

djwillis at users.sourceforge.net djwillis at users.sourceforge.net
Sat Apr 18 21:55:58 CEST 2009


Revision: 39991
          http://scummvm.svn.sourceforge.net/scummvm/?rev=39991&view=rev
Author:   djwillis
Date:     2009-04-18 19:55:58 +0000 (Sat, 18 Apr 2009)

Log Message:
-----------
Merge in some updates to the GP2X port for 0.13.1.

Modified Paths:
--------------
    scummvm/branches/branch-0-13-0/backends/platform/gp2x/events.cpp
    scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x-common.h
    scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x.cpp
    scummvm/branches/branch-0-13-0/backends/platform/gp2x/graphics.cpp

Modified: scummvm/branches/branch-0-13-0/backends/platform/gp2x/events.cpp
===================================================================
--- scummvm/branches/branch-0-13-0/backends/platform/gp2x/events.cpp	2009-04-18 19:46:23 UTC (rev 39990)
+++ scummvm/branches/branch-0-13-0/backends/platform/gp2x/events.cpp	2009-04-18 19:55:58 UTC (rev 39991)
@@ -30,6 +30,7 @@
 
 #include "backends/platform/gp2x/gp2x-common.h"
 #include "backends/platform/gp2x/gp2x-hw.h"
+#include "backends/keymapper/keymapper.h"
 #include "common/util.h"
 #include "common/events.h"
 
@@ -90,9 +91,9 @@
 
 	// Adjust for the screen scaling
 	if (!_overlayVisible) {
-		event.mouse.x /= _scaleFactor;
-		event.mouse.y /= _scaleFactor;
-		if (_adjustAspectRatio)
+		event.mouse.x /= _videoMode.scaleFactor;
+		event.mouse.y /= _videoMode.scaleFactor;
+		if (_videoMode.aspectRatio)
 			event.mouse.y = aspect2Real(event.mouse.y);
 	}
 }
@@ -161,7 +162,7 @@
 				_km.y_down_count = 1;
 			}
 
-			SDL_WarpMouse(_km.x, _km.y);
+			SDL_WarpMouse((Uint16)_km.x, (Uint16)_km.y);
 		}
 	}
 }
@@ -257,7 +258,6 @@
 	if (_modeChanged) {
 		_modeChanged = false;
 		event.type = Common::EVENT_SCREEN_CHANGED;
-		_screenChangeCount++;
 		return true;
 	}
 
@@ -593,3 +593,62 @@
 	return false;
 }
 
+void OSystem_GP2X::setupKeymapper() {
+#ifdef ENABLE_KEYMAPPER
+	using namespace Common;
+	Keymapper *mapper = getEventManager()->getKeymapper();
+
+	HardwareKeySet *keySet = new HardwareKeySet();
+	keySet->addHardwareKey(new HardwareKey( "a", KeyState(KEYCODE_a), "a", kActionKeyType ));
+	keySet->addHardwareKey(new HardwareKey( "s", KeyState(KEYCODE_s), "s", kActionKeyType ));
+	keySet->addHardwareKey(new HardwareKey( "d", KeyState(KEYCODE_d), "d", kActionKeyType ));
+	keySet->addHardwareKey(new HardwareKey( "f", KeyState(KEYCODE_f), "f", kActionKeyType ));
+	keySet->addHardwareKey(new HardwareKey( "n", KeyState(KEYCODE_n), "n (vk)", kTriggerLeftKeyType, kVirtualKeyboardActionType ));
+	keySet->addHardwareKey(new HardwareKey( "m", KeyState(KEYCODE_m), "m (remap)", kTriggerRightKeyType, kKeyRemapActionType ));
+	keySet->addHardwareKey(new HardwareKey( "[", KeyState(KEYCODE_LEFTBRACKET), "[ (select)", kSelectKeyType ));
+	keySet->addHardwareKey(new HardwareKey( "]", KeyState(KEYCODE_RIGHTBRACKET), "] (start)", kStartKeyType ));
+	mapper->registerHardwareKeySet(keySet);
+
+	Keymap *globalMap = new Keymap("global");
+	Keymap *guiMap = new Keymap("gui");
+	Action *act;
+	Event evt ;
+
+	act = new Action(globalMap, "MENU", "Menu", kGenericActionType, kSelectKeyType);
+	act->addKeyEvent(KeyState(KEYCODE_F5, ASCII_F5, 0));
+
+	act = new Action(globalMap, "SKCT", "Skip", kGenericActionType, kActionKeyType);
+	act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
+
+	act = new Action(globalMap, "PAUS", "Pause", kGenericActionType, kStartKeyType);
+	act->addKeyEvent(KeyState(KEYCODE_SPACE, ' ', 0));
+
+	act = new Action(globalMap, "SKLI", "Skip line", kGenericActionType, kActionKeyType);
+	act->addKeyEvent(KeyState(KEYCODE_PERIOD, '.', 0));
+
+	act = new Action(globalMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
+	act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0));
+
+	act = new Action(globalMap, "REMP", "Remap keys", kKeyRemapActionType);
+	act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
+
+	mapper->addGlobalKeymap(globalMap);
+
+	act = new Action(guiMap, "CLOS", "Close", kGenericActionType, kStartKeyType);
+	act->addKeyEvent(KeyState(KEYCODE_ESCAPE, ASCII_ESCAPE, 0));
+
+	act = new Action(guiMap, "CLIK", "Mouse click");
+	act->addLeftClickEvent();
+
+	act = new Action(guiMap, "VIRT", "Display keyboard", kVirtualKeyboardActionType);
+	act->addKeyEvent(KeyState(KEYCODE_F6, ASCII_F6, 0));
+
+	act = new Action(guiMap, "REMP", "Remap keys", kKeyRemapActionType);
+	act->addKeyEvent(KeyState(KEYCODE_F7, ASCII_F7, 0));
+
+	mapper->addGlobalKeymap(guiMap);
+
+	mapper->pushKeymap("global");
+#endif
+}
+

Modified: scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x-common.h
===================================================================
--- scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x-common.h	2009-04-18 19:46:23 UTC (rev 39990)
+++ scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x-common.h	2009-04-18 19:55:58 UTC (rev 39991)
@@ -26,22 +26,23 @@
 #ifndef GP2X_COMMON_H
 #define GP2X_COMMON_H
 
-#define __GP2X__
-#define USE_OSD
+#include <SDL.h>
+#include <SDL_gp2x.h>
 
 #include "common/scummsys.h"
 #include "common/system.h"
 #include "graphics/scaler.h"
 
-#include <SDL.h>
-#include <SDL_gp2x.h>
+#define __GP2X__
+#define USE_OSD
+/* #define DISABLE_SCALERS
+#define MIXER_DOUBLE_BUFFERING 1 */
 
+
 namespace Audio {
 	class MixerImpl;
 }
 
-//#define DISABLE_SCALERS
-
 enum {
 	GFX_NORMAL = 0,
 	GFX_DOUBLESIZE = 1,
@@ -66,11 +67,12 @@
 	virtual void initBackend();
 
 	void beginGFXTransaction(void);
-	void endGFXTransaction(void);
+	TransactionError endGFXTransaction(void);
 
 	// Set the size of the video bitmap.
 	// Typically, 320x200
 	void initSize(uint w, uint h);
+
 	int getScreenChangeID() const { return _screenChangeCount; }
 
 	// Set colors of the palette
@@ -107,7 +109,7 @@
 	void disableCursorPalette(bool disable) {
 		_cursorPaletteDisabled = disable;
 		blitCursor();
-	};
+	}
 
 	// Shaking is used in SCUMM. Set current shake position.
 	void setShakePos(int shake_pos);
@@ -122,9 +124,15 @@
 	// Returns true if an event was retrieved.
 	virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
 
+	// Sets up the keymapper with the backends hardware key set
+	void setupKeymapper();
+
 	// Set function that generates samples
 	void setupMixer();
 	static void mixCallback(void *s, byte *samples, int len);
+
+	void closeMixer();
+
 	virtual Audio::Mixer *getMixer();
 
 	// Poll CD status
@@ -153,6 +161,7 @@
 	void deleteMutex(MutexRef mutex);
 
 	// Overlay
+	Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
 	void showOverlay();
 	void hideOverlay();
 	void clearOverlay();
@@ -160,8 +169,8 @@
 	void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
 	int16 getHeight();
 	int16 getWidth();
-	int16 getOverlayHeight()  { return _overlayHeight; }
-	int16 getOverlayWidth()   { return _overlayWidth; }
+	int16 getOverlayHeight()  { return _videoMode.overlayHeight; }
+	int16 getOverlayWidth()   { return _videoMode.overlayWidth; }
 
 	const GraphicsMode *getSupportedGraphicsModes() const;
 	int getDefaultGraphicsMode() const;
@@ -177,7 +186,12 @@
 	void displayMessageOnOSD(const char *msg);
 
 	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;
 
@@ -196,7 +210,6 @@
 
 	// unseen game screen
 	SDL_Surface *_screen;
-	int _screenWidth, _screenHeight;
 
 	// temporary screen (for scalers)
 	SDL_Surface *_tmpscreen;
@@ -204,8 +217,8 @@
 
 	// overlay
 	SDL_Surface *_overlayscreen;
-	int _overlayWidth, _overlayHeight;
 	bool _overlayVisible;
+	Graphics::PixelFormat _overlayFormat;
 
 	// Audio
 	int _samplesPerSec;
@@ -216,42 +229,44 @@
 	uint32 _cdEndTime, _cdStopTime;
 
 	enum {
-		DF_WANT_RECT_OPTIM			= 1 << 0,
-		DF_UPDATE_EXPAND_1_PIXEL	= 1 << 1
+		DF_WANT_RECT_OPTIM			= 1 << 0
 	};
 
 	enum {
 		kTransactionNone = 0,
-		kTransactionCommit = 1,
-		kTransactionActive = 2
+		kTransactionActive = 1,
+		kTransactionRollback = 2
 	};
 
 	struct TransactionDetails {
-		int mode;
-		bool modeChanged;
-		int w;
-		int h;
 		bool sizeChanged;
-		bool fs;
-		bool fsChanged;
-		bool ar;
-		bool arChanged;
 		bool needHotswap;
 		bool needUpdatescreen;
-		bool needUnload;
-		bool needToggle;
 		bool normal1xScaler;
 	};
 	TransactionDetails _transactionDetails;
 
+	struct VideoState {
+		bool setup;
+
+		bool fullscreen;
+		bool aspectRatio;
+
+		int mode;
+		int scaleFactor;
+
+		int screenWidth, screenHeight;
+		int overlayWidth, overlayHeight;
+	};
+	VideoState _videoMode, _oldVideoMode;
+
+	virtual void setGraphicsModeIntern(); // overloaded by CE backend
+
 	/** Force full redraw on next updateScreen */
 	bool _forceFull;
 	ScalerProc *_scalerProc;
 	int _scalerType;
-	int _scaleFactor;
-	int _mode;
 	int _transactionMode;
-	bool _fullscreen;
 
 	bool _screenIsLocked;
 	Graphics::Surface _framebuffer;
@@ -270,7 +285,6 @@
 
 	enum {
 		NUM_DIRTY_RECT = 100,
-
 		MAX_MOUSE_W = 80,
 		MAX_MOUSE_H = 80,
 		MAX_SCALING = 3
@@ -353,32 +367,50 @@
 	 */
 	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;
-	FilesystemFactory *getFilesystemFactory();
-
 	Audio::MixerImpl *_mixer;
 
 	SDL_TimerID _timerID;
 	Common::TimerManager *_timer;
 
+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);
 
 	void drawMouse();
-	virtual void undrawMouse();
-	virtual void blitCursor();
+	void undrawMouse();
+	void blitCursor();
 
 	/** Set the position of the virtual mouse cursor. */
 	void setMousePos(int x, int y);
 	void fillMouseEvent(Common::Event &event, int x, int y);
+	void toggleMouseGrab();
 
 	void internUpdateScreen();
 
-	void loadGFXMode();
+	bool loadGFXMode();
 	void unloadGFXMode();
-	void hotswapGFXMode();
+	bool hotswapGFXMode();
 
 	void setFullscreenMode(bool enable);
 	void setAspectRatioCorrection(bool enable);
@@ -387,7 +419,10 @@
 
 	bool saveScreenshot(const char *filename);
 
-	int effectiveScreenHeight() const { return (_adjustAspectRatio ? 240 : _screenHeight) * _scaleFactor; }
+	int effectiveScreenHeight() const {
+		return (_videoMode.aspectRatio ? real2Aspect(_videoMode.screenHeight) : _videoMode.screenHeight)
+			* _videoMode.scaleFactor;
+	}
 
 	void setupIcon();
 	void handleKbdMouse();

Modified: scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x.cpp
===================================================================
--- scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x.cpp	2009-04-18 19:46:23 UTC (rev 39990)
+++ scummvm/branches/branch-0-13-0/backends/platform/gp2x/gp2x.cpp	2009-04-18 19:55:58 UTC (rev 39991)
@@ -31,15 +31,19 @@
 #include "backends/platform/gp2x/gp2x-common.h"
 #include "backends/platform/gp2x/gp2x-hw.h"
 #include "backends/platform/gp2x/gp2x-mem.h"
+#include "common/archive.h"
 #include "common/config-manager.h"
+
+#include "common/events.h"
+#include "common/util.h"
+
 #include "common/file.h"
-#include "common/util.h"
 #include "base/main.h"
 
-#include "backends/saves/default/default-saves.h"
+#include "backends/saves/posix/posix-saves.h"
+
 #include "backends/timer/default/default-timer.h"
 #include "backends/plugins/posix/posix-provider.h"
-#include "backends/fs/posix/posix-fs-factory.h" // for getFilesystemFactory()
 #include "sound/mixer_intern.h"
 
 #include <stdio.h>
@@ -48,20 +52,18 @@
 #include <limits.h>
 #include <errno.h>
 #include <sys/stat.h>
-#include <time.h> // for getTimeAndDate()
+#include <time.h>	// for getTimeAndDate()
 
 // Disable for normal serial logging.
 #define DUMP_STDOUT
 
-#if defined(HAVE_CONFIG_H)
-#include "config.h"
-#endif
-
 #define SAMPLES_PER_SEC 11025
 //#define SAMPLES_PER_SEC 22050
 //#define SAMPLES_PER_SEC 44100
 
+#define DEFAULT_CONFIG_FILE ".scummvmrc"
 
+#include "backends/fs/posix/posix-fs-factory.h"
 
 static Uint32 timer_handler(Uint32 interval, void *param) {
 	((DefaultTimerManager *)param)->handler();
@@ -106,8 +108,6 @@
 		error("Could not initialize SDL: %s", SDL_GetError());
 	}
 
-	SDL_ShowCursor(SDL_DISABLE);
-
 	// Setup default save path to be workingdir/saves
 	#ifndef PATH_MAX
 		#define PATH_MAX 255
@@ -191,6 +191,10 @@
 		setbuf(stderr, NULL);			/* No buffering */
 	#endif // DUMP_STDOUT
 
+	_graphicsMutex = createMutex();
+
+	SDL_ShowCursor(SDL_DISABLE);
+
 	// Setup other defaults.
 
 	ConfMan.registerDefault("aspect_ratio", true);
@@ -199,14 +203,15 @@
 	ConfMan.registerDefault("speech_volume", 220);
 	ConfMan.registerDefault("autosave_period", 3 * 60);	// Trigger autosave every 3 minutes - On low batts 4 mins is about your warning time.
 
-	_graphicsMutex = createMutex();
+	memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
+	memset(&_videoMode, 0, sizeof(_videoMode));
+	memset(&_transactionDetails, 0, sizeof(_transactionDetails));
 
 	_cksumValid = false;
-	_mode = GFX_NORMAL;
-	_scaleFactor = 0;
+	_videoMode.mode = GFX_NORMAL;
+	_videoMode.scaleFactor = 1;
 	_scalerProc = Normal1x;
-	_fullscreen = true;
-	_adjustAspectRatio = ConfMan.getBool("aspect_ratio");
+	_videoMode.aspectRatio  = ConfMan.getBool("aspect_ratio");
 	_scalerType = 0;
 	_modeFlags = 0;
 	_adjustZoomOnMouse = false;
@@ -220,7 +225,7 @@
 	// Create the savefile manager, if none exists yet (we check for this to
 	// allow subclasses to provide their own).
 	if (_savefile == 0) {
-		_savefile = new DefaultSaveFileManager(savePath);
+	_savefile = new POSIXSaveFileManager();
 	}
 
 	// Create and hook up the mixer, if none exists yet (we check for this to
@@ -229,16 +234,21 @@
 		setupMixer();
 	}
 
+	// Setup the keymapper with backend's set of keys
+	// NOTE: must be done before creating TimerManager
+	// to avoid race conditions in creating EventManager
+	setupKeymapper();
+
 	// 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) {
-		// TODO: We could implement a custom SDLTimerManager by using
+		// 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.
-		// Unfortunately, not all our code is prepared for that, so we can't just
-		// switch. But it's a long term goal to do just that!
+		// 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);
 
@@ -277,8 +287,7 @@
 OSystem_GP2X::OSystem_GP2X()
 	:
 	_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
-	_hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
-	_tmpscreen(0), _overlayWidth(0), _overlayHeight(0),
+	_hwscreen(0), _screen(0), _tmpscreen(0),
 	_overlayVisible(false),
 	_overlayscreen(0), _tmpscreen2(0),
 	_samplesPerSec(0),
@@ -288,9 +297,15 @@
 	_joystick(0),
 	_currentShakePos(0), _newShakePos(0),
 	_paletteDirtyStart(0), _paletteDirtyEnd(0),
+#ifdef MIXER_DOUBLE_BUFFERING
+	_soundMutex(0), _soundCond(0), _soundThread(0),
+	_soundThreadIsRunning(false), _soundThreadShouldQuit(false),
+#endif
+	_fsFactory(0),
 	_savefile(0),
 	_mixer(0),
 	_timer(0),
+	_screenIsLocked(false),
 	_graphicsMutex(0), _transactionMode(kTransactionNone) {
 
 	// allocate palette storage
@@ -304,11 +319,12 @@
 	memset(&_mouseCurState, 0, sizeof(_mouseCurState));
 
 	_inited = false;
+	_fsFactory = new POSIXFilesystemFactory();
 }
 
 OSystem_GP2X::~OSystem_GP2X() {
 	SDL_RemoveTimer(_timerID);
-	SDL_CloseAudio();
+	closeMixer();
 
 	free(_dirtyChecksums);
 	free(_currentPalette);
@@ -316,12 +332,13 @@
 	free(_mouseData);
 
 	delete _savefile;
-	delete _mixer;
 	delete _timer;
 }
 
 uint32 OSystem_GP2X::getMillis() {
-	return SDL_GetTicks();
+	uint32 millis = SDL_GetTicks();
+	getEventManager()->processMillis(millis);
+	return millis;
 }
 
 void OSystem_GP2X::delayMillis(uint msecs) {
@@ -344,13 +361,39 @@
 }
 
 FilesystemFactory *OSystem_GP2X::getFilesystemFactory() {
-	return &POSIXFilesystemFactory::instance();
+	assert(_fsFactory);
+	return _fsFactory;
 }
 
-//void OSystem_GP2X::setTimerCallback(TimerProc callback, int timer) {
-//	SDL_SetTimer(timer, (SDL_TimerCallback) callback);
-//}
+void OSystem_GP2X::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];
+	strcpy(configFile, DEFAULT_CONFIG_FILE);
+	return configFile;
+}
+
+Common::SeekableReadStream *OSystem_GP2X::openConfigFileForReading() {
+	Common::FSNode file(getDefaultConfigFileName());
+	return file.openForReading();
+}
+
+Common::WriteStream *OSystem_GP2X::openConfigFileForWriting() {
+	Common::FSNode file(getDefaultConfigFileName());
+	return file.openForWriting();
+}
+
 bool OSystem_GP2X::hasFeature(Feature f) {
 	return
 		(f == kFeatureFullscreenMode) ||
@@ -386,10 +429,8 @@
 	switch (f) {
 	case kFeatureFullscreenMode:
 		return false;
-	//case kFeatureFullscreenMode:
-	//	return _fullscreen;
 	case kFeatureAspectRatioCorrection:
-		return _adjustAspectRatio;
+		return _videoMode.aspectRatio;
 	case kFeatureAutoComputeDirtyRects:
 		return _modeFlags & DF_WANT_RECT_OPTIM;
 	default:
@@ -407,7 +448,7 @@
 	GP2X_device_deinit();
 
 	SDL_RemoveTimer(_timerID);
-	SDL_CloseAudio();
+	closeMixer();
 
 	free(_dirtyChecksums);
 	free(_currentPalette);
@@ -415,9 +456,8 @@
 	free(_mouseData);
 
 	delete _savefile;
-	delete _mixer;
 	delete _timer;
-
+	SDL_ShowCursor(SDL_ENABLE);
 	SDL_Quit();
 
 	delete getEventManager();
@@ -445,20 +485,114 @@
 #pragma mark --- Audio ---
 #pragma mark -
 
+#ifdef MIXER_DOUBLE_BUFFERING
+
+void OSystem_GP2X::mixerProducerThread() {
+	byte nextSoundBuffer;
+
+	SDL_LockMutex(_soundMutex);
+	while (true) {
+		// Wait till we are allowed to produce data
+		SDL_CondWait(_soundCond, _soundMutex);
+
+		if (_soundThreadShouldQuit)
+			break;
+
+		// Generate samples and put them into the next buffer
+		nextSoundBuffer = _activeSoundBuf ^ 1;
+		_mixer->mixCallback(_soundBuffers[nextSoundBuffer], _soundBufSize);
+
+		// Swap buffers
+		_activeSoundBuf = nextSoundBuffer;
+	}
+	SDL_UnlockMutex(_soundMutex);
+}
+
+int SDLCALL OSystem_GP2X::mixerProducerThreadEntry(void *arg) {
+	OSystem_GP2X *this_ = (OSystem_GP2X *)arg;
+	assert(this_);
+	this_->mixerProducerThread();
+	return 0;
+}
+
+
+void OSystem_GP2X::initThreadedMixer(Audio::MixerImpl *mixer, uint bufSize) {
+	_soundThreadIsRunning = false;
+	_soundThreadShouldQuit = false;
+
+	// Create mutex and condition variable
+	_soundMutex = SDL_CreateMutex();
+	_soundCond = SDL_CreateCond();
+
+	// Create two sound buffers
+	_activeSoundBuf = 0;
+	_soundBufSize = bufSize;
+	_soundBuffers[0] = (byte *)calloc(1, bufSize);
+	_soundBuffers[1] = (byte *)calloc(1, bufSize);
+
+	_soundThreadIsRunning = true;
+
+	// Finally start the thread
+	_soundThread = SDL_CreateThread(mixerProducerThreadEntry, this);
+}
+
+void OSystem_GP2X::deinitThreadedMixer() {
+	// Kill thread?? _soundThread
+
+	if (_soundThreadIsRunning) {
+		// Signal the producer thread to end, and wait for it to actually finish.
+		_soundThreadShouldQuit = true;
+		SDL_CondBroadcast(_soundCond);
+		SDL_WaitThread(_soundThread, NULL);
+
+		// Kill the mutex & cond variables.
+		// Attention: AT this point, the mixer callback must not be running
+		// anymore, else we will crash!
+		SDL_DestroyMutex(_soundMutex);
+		SDL_DestroyCond(_soundCond);
+
+		_soundThreadIsRunning = false;
+
+		free(_soundBuffers[0]);
+		free(_soundBuffers[1]);
+	}
+}
+
+
+void OSystem_GP2X::mixCallback(void *arg, byte *samples, int len) {
+	OSystem_GP2X *this_ = (OSystem_GP2X *)arg;
+	assert(this_);
+	assert(this_->_mixer);
+
+	assert((int)this_->_soundBufSize == len);
+
+	// Lock mutex, to ensure our data is not overwritten by the producer thread
+	SDL_LockMutex(this_->_soundMutex);
+
+	// Copy data from the current sound buffer
+	memcpy(samples, this_->_soundBuffers[this_->_activeSoundBuf], len);
+
+	// Unlock mutex and wake up the produced thread
+	SDL_UnlockMutex(this_->_soundMutex);
+	SDL_CondSignal(this_->_soundCond);
+}
+
+#else
+
 void OSystem_GP2X::mixCallback(void *sys, byte *samples, int len) {
 	OSystem_GP2X *this_ = (OSystem_GP2X *)sys;
 	assert(this_);
+	assert(this_->_mixer);
 
-	if (this_->_mixer)
-		this_->_mixer->mixCallback(samples, len);
+	this_->_mixer->mixCallback(samples, len);
 }
 
+#endif
+
 void OSystem_GP2X::setupMixer() {
 	SDL_AudioSpec desired;
 	SDL_AudioSpec obtained;
 
-	//memset(&desired, 0, sizeof(desired));
-
 	// Determine the desired output sampling frequency.
 	_samplesPerSec = 0;
 	if (ConfMan.hasKey("output_rate"))
@@ -466,7 +600,6 @@
 	if (_samplesPerSec <= 0)
 		_samplesPerSec = SAMPLES_PER_SEC;
 
-
 	//Quick EVIL Hack - DJWillis
 	_samplesPerSec = 11025;
 
@@ -506,10 +639,31 @@
 		// Tell the mixer that we are ready and start the sound processing
 		_mixer->setOutputRate(_samplesPerSec);
 		_mixer->setReady(true);
+
+#ifdef MIXER_DOUBLE_BUFFERING
+		initThreadedMixer(_mixer, obtained.samples * 4);
+#endif
+
+		// start the sound system
 		SDL_PauseAudio(0);
 	}
 }
 
+void OSystem_GP2X::closeMixer() {
+	if (_mixer)
+		_mixer->setReady(false);
+
+	SDL_CloseAudio();
+
+	delete _mixer;
+	_mixer = 0;
+
+#ifdef MIXER_DOUBLE_BUFFERING
+	deinitThreadedMixer();
+#endif
+
+}
+
 Audio::Mixer *OSystem_GP2X::getMixer() {
 	assert(_mixer);
 	return _mixer;

Modified: scummvm/branches/branch-0-13-0/backends/platform/gp2x/graphics.cpp
===================================================================
--- scummvm/branches/branch-0-13-0/backends/platform/gp2x/graphics.cpp	2009-04-18 19:46:23 UTC (rev 39990)
+++ scummvm/branches/branch-0-13-0/backends/platform/gp2x/graphics.cpp	2009-04-18 19:55:58 UTC (rev 39991)
@@ -70,116 +70,246 @@
 }
 
 void OSystem_GP2X::beginGFXTransaction(void) {
-	assert (_transactionMode == kTransactionNone);
+	assert(_transactionMode == kTransactionNone);
 
 	_transactionMode = kTransactionActive;
 
-	_transactionDetails.modeChanged = false;
 	_transactionDetails.sizeChanged = false;
-	_transactionDetails.arChanged = false;
-	_transactionDetails.fsChanged = false;
 
 	_transactionDetails.needHotswap = false;
 	_transactionDetails.needUpdatescreen = false;
-	_transactionDetails.needUnload = false;
 
 	_transactionDetails.normal1xScaler = false;
+
+	_oldVideoMode = _videoMode;
 }
 
-void OSystem_GP2X::endGFXTransaction(void) {
-	// for each engine we run initCommonGFX() as first thing in the transaction
-	// and initSize() is called later. If user runs launcher at 320x200 with
-	// 2x overlay, setting to Nomral1x sclaler in that case will be suppressed
-	// and backend is forced to 2x
-	//
-	// This leads to bad results such as 1280x960 window for 640x480 engines.
-	// To prevent that we rerun setGraphicsMode() if there was 1x scaler request
-	if (_transactionDetails.normal1xScaler)
-		setGraphicsMode(GFX_NORMAL);
+OSystem::TransactionError OSystem_GP2X::endGFXTransaction(void) {
+	int errors = kTransactionSuccess;
 
-	assert (_transactionMode == kTransactionActive);
+	assert(_transactionMode != kTransactionNone);
 
-	_transactionMode = kTransactionCommit;
-	if (_transactionDetails.modeChanged)
-		setGraphicsMode(_transactionDetails.mode);
+	if (_transactionMode == kTransactionRollback) {
+		if (_videoMode.fullscreen != _oldVideoMode.fullscreen) {
+			errors |= kTransactionFullscreenFailed;
 
-	if (_transactionDetails.sizeChanged)
-		initSize(_transactionDetails.w, _transactionDetails.h);
+			_videoMode.fullscreen = _oldVideoMode.fullscreen;
+		} else if (_videoMode.aspectRatio != _oldVideoMode.aspectRatio) {
+			errors |= kTransactionAspectRatioFailed;
 
-	if (_transactionDetails.arChanged)
-		setAspectRatioCorrection(_transactionDetails.ar);
+			_videoMode.aspectRatio = _oldVideoMode.aspectRatio;
+		} else if (_videoMode.mode != _oldVideoMode.mode) {
+			errors |= kTransactionModeSwitchFailed;
 
-	if (_transactionDetails.needUnload) {
+			_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();
-		loadGFXMode();
-		clearOverlay();
-	} else {
-		if (!_transactionDetails.fsChanged) {
-			if (_transactionDetails.needHotswap)
-				hotswapGFXMode();
-			else if (_transactionDetails.needUpdatescreen)
+		if (!loadGFXMode()) {
+			if (_oldVideoMode.setup) {
+				_transactionMode = kTransactionRollback;
+				errors |= endGFXTransaction();
+			}
+		} else {
+			setGraphicsModeIntern();
+			clearOverlay();
+
+			_videoMode.setup = true;
+			_modeChanged = true;
+			// OSystem_SDL::pollEvent used to update the screen change count,
+			// but actually it gives problems when a video mode was changed
+			// but OSystem_SDL::pollEvent was not called. This for example
+			// caused a crash under certain circumstances when doing an RTL.
+			// To fix this issue we update the screen change count right here.
+			_screenChangeCount++;
+		}
+	} else if (_transactionDetails.needHotswap) {
+		setGraphicsModeIntern();
+		if (!hotswapGFXMode()) {
+			if (_oldVideoMode.setup) {
+				_transactionMode = kTransactionRollback;
+				errors |= endGFXTransaction();
+			}
+		} else {
+			_videoMode.setup = true;
+			_modeChanged = true;
+			// OSystem_SDL::pollEvent used to update the screen change count,
+			// but actually it gives problems when a video mode was changed
+			// but OSystem_SDL::pollEvent was not called. This for example
+			// caused a crash under certain circumstances when doing an RTL.
+			// To fix this issue we update the screen change count right here.
+			_screenChangeCount++;
+
+			if (_transactionDetails.needUpdatescreen)
 				internUpdateScreen();
 		}
+	} else if (_transactionDetails.needUpdatescreen) {
+		setGraphicsModeIntern();
+		internUpdateScreen();
 	}
 
-	if (_transactionDetails.fsChanged)
-		setFullscreenMode(_transactionDetails.fs);
-
 	_transactionMode = kTransactionNone;
+	return (TransactionError)errors;
 }
 
 bool OSystem_GP2X::setGraphicsMode(int mode) {
 	Common::StackLock lock(_graphicsMutex);
 
+	assert(_transactionMode == kTransactionActive);
+
+	if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
+		return true;
+
 	int newScaleFactor = 1;
-	ScalerProc *newScalerProc;
 
-	mode = GFX_NORMAL;
-	newScaleFactor = 1;
-	newScalerProc = Normal1x;
+	switch(mode) {
+	case GFX_NORMAL:
+		newScaleFactor = 1;
+		break;
+#ifndef DISABLE_SCALERS
+	case GFX_DOUBLESIZE:
+		newScaleFactor = 2;
+		break;
+	case GFX_TRIPLESIZE:
+		newScaleFactor = 3;
+		break;
 
+	case GFX_2XSAI:
+		newScaleFactor = 2;
+		break;
+	case GFX_SUPER2XSAI:
+		newScaleFactor = 2;
+		break;
+	case GFX_SUPEREAGLE:
+		newScaleFactor = 2;
+		break;
+	case GFX_ADVMAME2X:
+		newScaleFactor = 2;
+		break;
+	case GFX_ADVMAME3X:
+		newScaleFactor = 3;
+		break;
+#ifndef DISABLE_HQ_SCALERS
+	case GFX_HQ2X:
+		newScaleFactor = 2;
+		break;
+	case GFX_HQ3X:
+		newScaleFactor = 3;
+		break;
+#endif
+	case GFX_TV2X:
+		newScaleFactor = 2;
+		break;
+	case GFX_DOTMATRIX:
+		newScaleFactor = 2;
+		break;
+#endif // DISABLE_SCALERS
+
+	default:
+		warning("unknown gfx mode %d", mode);
+		return false;
+	}
+
 	_transactionDetails.normal1xScaler = (mode == GFX_NORMAL);
+	if (_oldVideoMode.setup && _oldVideoMode.scaleFactor != newScaleFactor)
+		_transactionDetails.needHotswap = true;
 
-	_mode = mode;
-	_scalerProc = newScalerProc;
+	_transactionDetails.needUpdatescreen = true;
 
-	if (_transactionMode == kTransactionActive) {
-		_transactionDetails.mode = mode;
-		_transactionDetails.modeChanged = true;
+	_videoMode.mode = mode;
+	_videoMode.scaleFactor = newScaleFactor;
 
-		if (newScaleFactor != _scaleFactor) {
-			_transactionDetails.needHotswap = true;
-			_scaleFactor = newScaleFactor;
-		}
+	return true;
+}
 
-		_transactionDetails.needUpdatescreen = true;
 
-		return true;
-	}
+void OSystem_GP2X::setGraphicsModeIntern() {
+	Common::StackLock lock(_graphicsMutex);
+	ScalerProc *newScalerProc = 0;
 
-	// NOTE: This should not be executed at transaction commit
-	//   Otherwise there is some unsolicited setGraphicsMode() call
-	//   which should be properly removed
-	if (newScaleFactor != _scaleFactor) {
-		assert(_transactionMode != kTransactionCommit);
+	switch (_videoMode.mode) {
+	case GFX_NORMAL:
+		newScalerProc = Normal1x;
+		break;
+#ifndef DISABLE_SCALERS
+	case GFX_DOUBLESIZE:
+		newScalerProc = Normal2x;
+		break;
+	case GFX_TRIPLESIZE:
+		newScalerProc = Normal3x;
+		break;
 
-		_scaleFactor = newScaleFactor;
-		hotswapGFXMode();
+	case GFX_2XSAI:
+		newScalerProc = _2xSaI;
+		break;
+	case GFX_SUPER2XSAI:
+		newScalerProc = Super2xSaI;
+		break;
+	case GFX_SUPEREAGLE:
+		newScalerProc = SuperEagle;
+		break;
+	case GFX_ADVMAME2X:
+		newScalerProc = AdvMame2x;
+		break;
+	case GFX_ADVMAME3X:
+		newScalerProc = AdvMame3x;
+		break;
+#ifndef DISABLE_HQ_SCALERS
+	case GFX_HQ2X:
+		newScalerProc = HQ2x;
+		break;
+	case GFX_HQ3X:
+		newScalerProc = HQ3x;
+		break;
+#endif
+	case GFX_TV2X:
+		newScalerProc = TV2x;
+		break;
+	case GFX_DOTMATRIX:
+		newScalerProc = DotMatrix;
+		break;
+#endif // DISABLE_SCALERS
+
+	default:
+		error("Unknown gfx mode %d", _videoMode.mode);
 	}
 
-	// Determine the "scaler type", i.e. essentially an index into the
-	// s_gfxModeSwitchTable array defined in events.cpp.
-	if (_mode != GFX_NORMAL) {
+	_scalerProc = newScalerProc;
+
+	if (_videoMode.mode != GFX_NORMAL) {
 		for (int i = 0; i < ARRAYSIZE(s_gfxModeSwitchTable); i++) {
-			if (s_gfxModeSwitchTable[i][1] == _mode || s_gfxModeSwitchTable[i][2] == _mode) {
+			if (s_gfxModeSwitchTable[i][1] == _videoMode.mode || s_gfxModeSwitchTable[i][2] == _videoMode.mode) {
 				_scalerType = i;
 				break;
 			}
 		}
 	}
 
-	if (!_screen)
-		return true;
+	if (!_screen || !_hwscreen)
+		return;
 
 	// Blit everything to the screen
 	_forceFull = true;
@@ -187,101 +317,79 @@
 	// Even if the old and new scale factors are the same, we may have a
 	// different scaler for the cursor now.
 	blitCursor();
-
-	if (_transactionMode != kTransactionCommit)
-		internUpdateScreen();
-
-	// Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
-	_modeChanged = true;
-
-	return true;
 }
 
 int OSystem_GP2X::getGraphicsMode() const {
 	assert (_transactionMode == kTransactionNone);
-	return _mode;
+	return _videoMode.mode;
 }
 
 void OSystem_GP2X::initSize(uint w, uint h){
+	assert(_transactionMode == kTransactionActive);
+
 	// Avoid redundant res changes
-	if ((int)w == _screenWidth && (int)h == _screenHeight &&
-		_transactionMode != kTransactionCommit)
+	if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)
 		return;
 
-	_screenWidth = w;
-	_screenHeight = h;
+	_videoMode.screenWidth = w;
+	_videoMode.screenHeight = h;
 
-	_cksumNum = (_screenWidth * _screenHeight / (8 * 8));
+	_cksumNum = (w * h / (8 * 8));
 
-	if (_transactionMode == kTransactionActive) {
-		_transactionDetails.w = w;
-		_transactionDetails.h = h;
-		_transactionDetails.sizeChanged = true;
+	_transactionDetails.sizeChanged = true;
 
-		_transactionDetails.needUnload = true;
-
-		return;
-	}
-
 	free(_dirtyChecksums);
 	_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
-
-	if (_transactionMode != kTransactionCommit) {
-		unloadGFXMode();
-		loadGFXMode();
-
-		// if initSize() gets called in the middle, overlay is not transparent
-		clearOverlay();
-	}
 }
 
-void OSystem_GP2X::loadGFXMode() {
+bool OSystem_GP2X::loadGFXMode() {
 	assert(_inited);
 	_forceFull = true;
-	_modeFlags |= DF_UPDATE_EXPAND_1_PIXEL;
 
 	int hwW, hwH;
 
-	_overlayWidth = _screenWidth * _scaleFactor;
-	_overlayHeight = _screenHeight * _scaleFactor;
+	_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+	_videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
 
-	if (_screenHeight != 200)
-		_adjustAspectRatio = false;
+	if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
+		_videoMode.aspectRatio = false;
 
-	if (_adjustAspectRatio)
-		_overlayHeight = real2Aspect(_overlayHeight);
+	if (_videoMode.aspectRatio)
+		_videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
 
-	hwW = _screenWidth * _scaleFactor;
+	hwW = _videoMode.screenWidth * _videoMode.scaleFactor;
 	hwH = effectiveScreenHeight();
 
 	//
 	// Create the surface that contains the 8 bit game data
 	//
-	_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
+	_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 graphics in 16 bit mode
+	// Create the surface that contains the scaled graphics in 16 bit mode
 	//
 
-	// FIXME: Hack for GP2X SDL querks.
-	if (_screenWidth <= 320) {
-		_hwscreen = SDL_SetVideoMode(320, 240, 16, SDL_FULLSCREEN|SDL_SWSURFACE);
-	} else {
-		_hwscreen = SDL_SetVideoMode(_screenWidth, _screenHeight, 16, SDL_FULLSCREEN|SDL_SWSURFACE);
-	}
+	_hwscreen = SDL_SetVideoMode(hwW, hwH, 16,
+		_videoMode.fullscreen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE
+	);
+	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 (_hwscreen == NULL) {
-		warning("SDL_SetVideoMode says we can't switch to that mode");
-		quit();
+		if (!_oldVideoMode.setup) {
+			warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
+			quit();
+		} else {
+			return false;
+		}
 	}
 
 	// GP2X Specific, must be called after any SDL_SetVideoMode to ensure the hardware cursor is off.
 	// Note: On the GP2X SDL_SetVideoMode recalls SDL_Init().
 	SDL_ShowCursor(SDL_DISABLE);
 
-
 	//
 	// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
 	//
@@ -293,7 +401,7 @@
 		InitScalers(565);
 
 	// Need some extra bytes around when using 2xSaI
-	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth + 3, _screenHeight + 3,
+	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,
 						16,
 						_hwscreen->format->Rmask,
 						_hwscreen->format->Gmask,
@@ -303,7 +411,7 @@
 	if (_tmpscreen == NULL)
 		error("allocating _tmpscreen failed");
 
-	_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth, _overlayHeight,
+	_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
 						16,
 						_hwscreen->format->Rmask,
 						_hwscreen->format->Gmask,
@@ -313,7 +421,19 @@
 	if (_overlayscreen == NULL)
 		error("allocating _overlayscreen failed");
 
-	_tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _overlayWidth + 3, _overlayHeight + 3,
+	_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,
@@ -336,10 +456,12 @@
 	SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey);
 
 	// keyboard cursor control, some other better place for it?
-	_km.x_max = _screenWidth * _scaleFactor - 1;
+	_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_GP2X::unloadGFXMode() {
@@ -372,29 +494,39 @@
 		SDL_FreeSurface(_osdSurface);
 		_osdSurface = NULL;
 	}
+	DestroyScalers();
 }
 
-void OSystem_GP2X::hotswapGFXMode() {
+bool OSystem_GP2X::hotswapGFXMode() {
 	if (!_screen)
-		return;
+		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);
+	SDL_FreeSurface(_hwscreen); _hwscreen = NULL;
 
-	SDL_FreeSurface(_tmpscreen);
-	SDL_FreeSurface(_tmpscreen2);
+	SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL;
+	SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL;
 
 	// Release the OSD surface
-	SDL_FreeSurface(_osdSurface);
+	SDL_FreeSurface(_osdSurface); _osdSurface = NULL;
 
 	// Setup the new GFX mode
-	loadGFXMode();
+	if (!loadGFXMode()) {
+		unloadGFXMode();
 
+		_screen = old_screen;
+		_overlayscreen = old_overlayscreen;
+
+		return false;
+	}
+
 	// reset palette
 	SDL_SetColors(_screen, _currentPalette, 0, 256);
 
@@ -412,8 +544,7 @@
 	// Blit everything to the screen
 	internUpdateScreen();
 
-	// Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
-	_modeChanged = true;
+	return true;
 }
 
 void OSystem_GP2X::updateScreen() {
@@ -437,9 +568,9 @@
 
 	// If the shake position changed, fill the dirty area with blackness
 	if (_currentShakePos != _newShakePos) {
-		SDL_Rect blackrect = {0, 0, _screenWidth * _scaleFactor, _newShakePos * _scaleFactor};
+		SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor};
 
-		if (_adjustAspectRatio && !_overlayVisible)
+		if (_videoMode.aspectRatio && !_overlayVisible)
 			blackrect.h = real2Aspect(blackrect.h - 1) + 1;
 
 		SDL_FillRect(_hwscreen, &blackrect, 0);
@@ -481,15 +612,15 @@
 	if (!_overlayVisible) {
 		origSurf = _screen;
 		srcSurf = _tmpscreen;
-		width = _screenWidth;
-		height = _screenHeight;
+		width = _videoMode.screenWidth;
+		height = _videoMode.screenHeight;
 		scalerProc = _scalerProc;
-		scale1 = _scaleFactor;
+		scale1 = _videoMode.scaleFactor;
 	} else {
 		origSurf = _overlayscreen;
 		srcSurf = _tmpscreen2;
-		width = _overlayWidth;
-		height = _overlayHeight;
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
 		scalerProc = Normal1x;
 
 		scale1 = 1;
@@ -513,17 +644,8 @@
 		uint32 srcPitch, dstPitch;
 		SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;
 
-		if (scalerProc == Normal1x && !_adjustAspectRatio && 0) {
 			for (r = _dirtyRectList; r != lastRect; ++r) {
 				dst = *r;
-
-				dst.y += _currentShakePos;
-				if (SDL_BlitSurface(origSurf, r, _hwscreen, &dst) != 0)
-					error("SDL_BlitSurface failed: %s", SDL_GetError());
-			}
-		} else {
-			for (r = _dirtyRectList; r != lastRect; ++r) {
-				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.
 
@@ -551,7 +673,7 @@
 					orig_dst_y = dst_y;
 					dst_y = dst_y * scale1;
 
-					if (_adjustAspectRatio && !_overlayVisible)
+				if (_videoMode.aspectRatio && !_overlayVisible)
 						dst_y = real2Aspect(dst_y);
 
 					assert(scalerProc != NULL);
@@ -565,13 +687,12 @@
 				r->h = dst_h * scale1;
 
 #ifndef DISABLE_SCALERS
-				if (_adjustAspectRatio && orig_dst_y < height && !_overlayVisible)
+			if (_videoMode.aspectRatio && orig_dst_y < height && !_overlayVisible)
 					r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1);
 #endif
 			}
 			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.
@@ -608,62 +729,28 @@
 void OSystem_GP2X::setFullscreenMode(bool enable) {
 	Common::StackLock lock(_graphicsMutex);
 
-	if (_fullscreen != enable || _transactionMode == kTransactionCommit) {
-		assert(_hwscreen != 0);
-		_fullscreen = enable;
+	if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
+		return;
 
-		if (_transactionMode == kTransactionActive) {
-			_transactionDetails.fs = enable;
-			_transactionDetails.fsChanged = true;
-
-			_transactionDetails.needHotswap = true;
-
-			return;
-		}
-
-#if (defined(MACOSX) && !SDL_VERSION_ATLEAST(1, 2, 6)) || defined(__MAEMO__)
-		// On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse,
-		// before SDL 1.2.6 it always returned -1 (which would indicate a
-		// successful switch). So we simply don't call it at all and use
-		// hotswapGFXMode() directly to switch to fullscreen mode.
-		hotswapGFXMode();
-#else
-		if (!SDL_WM_ToggleFullScreen(_hwscreen)) {
-			// if ToggleFullScreen fails, achieve the same effect with hotswap gfx mode
-			hotswapGFXMode();
-		} else {
-			// Blit everything to the screen
-			internUpdateScreen();
-
-			// Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
-			_modeChanged = true;
-		}
-#endif
+	if (_transactionMode == kTransactionActive) {
+		_videoMode.fullscreen = enable;
+		_transactionDetails.needHotswap = true;
 	}
 }
 
 void OSystem_GP2X::setAspectRatioCorrection(bool enable) {
-	if ((_screenHeight == 200 && _adjustAspectRatio != enable) ||
-		_transactionMode == kTransactionCommit) {
+
+	if ((_videoMode.screenHeight == 200 && _videoMode.aspectRatio != enable) ||
+		_transactionMode == kTransactionActive) {
 		Common::StackLock lock(_graphicsMutex);
+	}
 
-		//assert(_hwscreen != 0);
-		_adjustAspectRatio = enable;
+	if (_oldVideoMode.setup && _oldVideoMode.aspectRatio == enable)
+		return;
 
-		if (_transactionMode == kTransactionActive) {
-			_transactionDetails.ar = enable;
-			_transactionDetails.arChanged = true;
-
-			_transactionDetails.needHotswap = true;
-
-			return;
-		} else {
-			if (_transactionMode != kTransactionCommit)
-				hotswapGFXMode();
-		}
-
-		// Make sure that an Common::EVENT_SCREEN_CHANGED gets sent later
-		_modeChanged = true;
+	if (_transactionMode == kTransactionActive) {
+		_videoMode.aspectRatio = enable;
+		_transactionDetails.needHotswap = true;
 	}
 }
 
@@ -693,8 +780,8 @@
 //	assert(h > 0 && y + h <= _screenHeight);
 //	assert(w > 0 && x + w <= _screenWidth);
 
-	if (((long)src & 3) == 0 && pitch == _screenWidth && x == 0 && y == 0 &&
-			w == _screenWidth && h == _screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
+	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. */
@@ -713,12 +800,12 @@
 			y = 0;
 		}
 
-		if (w > _screenWidth - x) {
-			w = _screenWidth - x;
+		if (w > _videoMode.screenWidth - x) {
+			w = _videoMode.screenWidth - x;
 		}
 
-		if (h > _screenHeight - y) {
-			h = _screenHeight - y;
+		if (h > _videoMode.screenHeight - y) {
+			h = _videoMode.screenHeight - y;
 		}
 
 		if (w <= 0 || h <= 0)
@@ -732,15 +819,15 @@
 	if (SDL_LockSurface(_screen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
-	byte *dst = (byte *)_screen->pixels + y * _screenWidth + x;
+	byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth + x;
 
-	if (_screenWidth == pitch && pitch == w) {
+	if (_videoMode.screenWidth == pitch && pitch == w) {
 		memcpy(dst, src, h*w);
 	} else {
 		do {
 			memcpy(dst, src, w);
 			src += pitch;
-			dst += _screenWidth;
+			dst += _videoMode.screenWidth;
 		} while (--h);
 	}
 
@@ -800,16 +887,16 @@
 	int height, width;
 
 	if (!_overlayVisible && !realCoordinates) {
-		width = _screenWidth;
-		height = _screenHeight;
+		width = _videoMode.screenWidth;
+		height = _videoMode.screenHeight;
 	} else {
-		width = _overlayWidth;
-		height = _overlayHeight;
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
 	}
 
 	// Extend the dirty region by 1 pixel for scalers
 	// that "smear" the screen, e.g. 2xSAI
-	if ((_modeFlags & DF_UPDATE_EXPAND_1_PIXEL) && !realCoordinates) {
+	if (!realCoordinates) {
 		x--;
 		y--;
 		w+=2;
@@ -835,7 +922,7 @@
 		h = height - y;
 	}
 
-	if (_adjustAspectRatio && !_overlayVisible && !realCoordinates) {
+	if (_videoMode.aspectRatio && !_overlayVisible && !realCoordinates) {
 		makeRectStretchable(x, y, w, h);
 	}
 
@@ -858,14 +945,14 @@
 	assert(buf);
 	uint32 *sums = _dirtyChecksums;
 	uint x,y;
-	const uint last_x = (uint)_screenWidth / 8;
-	const uint last_y = (uint)_screenHeight / 8;
+	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 += _screenWidth * (8 - 1))
+	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
@@ -881,7 +968,7 @@
 					s1 += ptr[subX];
 					s2 += s1;
 				}
-				ptr += _screenWidth;
+				ptr += _videoMode.screenWidth;
 			}
 
 			s1 %= BASE;
@@ -911,8 +998,8 @@
 		int x, y, w;
 		uint32 *ck = _dirtyChecksums;
 
-		for (y = 0; y != _screenHeight / 8; y++) {
-			for (x = 0; x != _screenWidth / 8; x++, ck++) {
+		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. */
@@ -920,7 +1007,7 @@
 					do {
 						ck[w + _cksumNum] = ck[w];
 						w++;
-					} while (x + w != _screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
+					} while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
 
 					addDirtyRect(x * 8, y * 8, w * 8, 8);
 
@@ -937,11 +1024,11 @@
 }
 
 int16 OSystem_GP2X::getHeight() {
-	return _screenHeight;
+	return _videoMode.screenHeight;
 }
 
 int16 OSystem_GP2X::getWidth() {
-	return _screenWidth;
+	return _videoMode.screenWidth;
 }
 
 void OSystem_GP2X::setPalette(const byte *colors, uint start, uint num) {
@@ -1026,11 +1113,11 @@
 
 	// Since resolution could change, put mouse to adjusted position
 	// Fixes bug #1349059
-	x = _mouseCurState.x * _scaleFactor;
-	if (_adjustAspectRatio)
-		y = real2Aspect(_mouseCurState.y) * _scaleFactor;
+	x = _mouseCurState.x * _videoMode.scaleFactor;
+	if (_videoMode.aspectRatio)
+		y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor;
 	else
-		y = _mouseCurState.y * _scaleFactor;
+		y = _mouseCurState.y * _videoMode.scaleFactor;
 
 	warpMouse(x, y);
 
@@ -1049,9 +1136,9 @@
 
 	// Since resolution could change, put mouse to adjusted position
 	// Fixes bug #1349059
-	x = _mouseCurState.x / _scaleFactor;
-	y = _mouseCurState.y / _scaleFactor;
-	if (_adjustAspectRatio)
+	x = _mouseCurState.x / _videoMode.scaleFactor;
+	y = _mouseCurState.y / _videoMode.scaleFactor;
+	if (_videoMode.aspectRatio)
 		y = aspect2Real(y);
 
 	warpMouse(x, y);
@@ -1073,20 +1160,20 @@
 	SDL_Rect src, dst;
 	src.x = src.y = 0;
 	dst.x = dst.y = 1;
-	src.w = dst.w = _screenWidth;
-	src.h = dst.h = _screenHeight;
+	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, _screenWidth, _screenHeight);
+	(byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);
 
 #ifndef DISABLE_SCALERS
-	if (_adjustAspectRatio)
+	if (_videoMode.aspectRatio)
 		stretch200To240((uint8 *)_overlayscreen->pixels, _overlayscreen->pitch,
-						_overlayWidth, _screenHeight * _scaleFactor, 0, 0, 0);
+						_videoMode.overlayWidth, _videoMode.screenHeight * _videoMode.scaleFactor, 0, 0, 0);
 #endif
 	SDL_UnlockSurface(_tmpscreen);
 	SDL_UnlockSurface(_overlayscreen);
@@ -1104,9 +1191,9 @@
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
 	byte *src = (byte *)_overlayscreen->pixels;
-	int h = _overlayHeight;
+	int h = _videoMode.overlayHeight;
 	do {
-		memcpy(buf, src, _overlayWidth * 2);
+		memcpy(buf, src, _videoMode.overlayWidth * 2);
 		src += _overlayscreen->pitch;
 		buf += pitch;
 	} while (--h);
@@ -1132,12 +1219,12 @@
 		y = 0;
 	}
 
-	if (w > _overlayWidth - x) {
-		w = _overlayWidth - x;
+	if (w > _videoMode.overlayWidth - x) {
+		w = _videoMode.overlayWidth - x;
 	}
 
-	if (h > _overlayHeight - y) {
-		h = _overlayHeight - y;
+	if (h > _videoMode.overlayHeight - y) {
+		h = _videoMode.overlayHeight - y;
 	}
 
 	if (w <= 0 || h <= 0)
@@ -1190,7 +1277,7 @@
 
 	if (_mouseCurState.x != x || _mouseCurState.y != y) {
 		if (!_overlayVisible)
-			SDL_WarpMouse(x * _scaleFactor, y1 * _scaleFactor);
+			SDL_WarpMouse(x * _videoMode.scaleFactor, y1 * _videoMode.scaleFactor);
 		else
 			SDL_WarpMouse(x, y1);
 
@@ -1293,7 +1380,7 @@
 
 	int rW, rH;
 
-	if (_cursorTargetScale >= _scaleFactor) {
+	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
@@ -1306,22 +1393,22 @@
 
 		// The virtual dimensions may be larger than the original.
 
-		_mouseCurState.vW = w * _cursorTargetScale / _scaleFactor;
-		_mouseCurState.vH = h * _cursorTargetScale / _scaleFactor;
+		_mouseCurState.vW = w * _cursorTargetScale / _videoMode.scaleFactor;
+		_mouseCurState.vH = h * _cursorTargetScale / _videoMode.scaleFactor;
 		_mouseCurState.vHotX = _mouseCurState.hotX * _cursorTargetScale /
-			_scaleFactor;
+			_videoMode.scaleFactor;
 		_mouseCurState.vHotY = _mouseCurState.hotY * _cursorTargetScale /
-			_scaleFactor;
+			_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 * _scaleFactor / _cursorTargetScale;
-		rH = h * _scaleFactor / _cursorTargetScale;
-		_mouseCurState.rHotX = _mouseCurState.hotX * _scaleFactor /
+		rW = w * _videoMode.scaleFactor / _cursorTargetScale;
+		rH = h * _videoMode.scaleFactor / _cursorTargetScale;
+		_mouseCurState.rHotX = _mouseCurState.hotX * _videoMode.scaleFactor /
 			_cursorTargetScale;
-		_mouseCurState.rHotY = _mouseCurState.hotY * _scaleFactor /
+		_mouseCurState.rHotY = _mouseCurState.hotY * _videoMode.scaleFactor /
 			_cursorTargetScale;
 
 		// The virtual dimensions will be the same as the original.
@@ -1333,7 +1420,8 @@
 	}
 
 	int rH1 = rH; // store original to pass to aspect-correction function later
-	if (_adjustAspectRatio && _cursorTargetScale == 1) {
+
+	if (_videoMode.aspectRatio && _cursorTargetScale == 1) {
 		rH = real2Aspect(rH - 1) + 1;
 		_mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);
 	}
@@ -1368,16 +1456,16 @@
 	// the game. This only works well with the non-blurring scalers so we
 	// actually only use the 1x, 1.5x, 2x and AdvMame scalers.
 
-	if (_cursorTargetScale == 1 && (_mode == GFX_DOUBLESIZE || _mode == GFX_TRIPLESIZE))
+	if (_cursorTargetScale == 1 && (_videoMode.mode == GFX_DOUBLESIZE || _videoMode.mode == GFX_TRIPLESIZE))
 		scalerProc = _scalerProc;
 	else
-		scalerProc = scalersMagn[_cursorTargetScale - 1][_scaleFactor - 1];
+		scalerProc = scalersMagn[_cursorTargetScale - 1][_videoMode.scaleFactor - 1];
 
 	scalerProc((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2,
 		_mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch,
 		_mouseCurState.w, _mouseCurState.h);
 
-	if (_adjustAspectRatio && _cursorTargetScale == 1)
+	if (_videoMode.aspectRatio && _cursorTargetScale == 1)
 		cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, rW, rH1, 0, 0, 0);
 
 	SDL_UnlockSurface(_mouseSurface);
@@ -1404,13 +1492,20 @@
 	return 1 + maxDstY - srcY;
 }
 
+void OSystem_GP2X::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_GP2X::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 >= _screenWidth || y >= _screenHeight)) {
+	if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight)) {
 		return;
 	}
 
@@ -1432,14 +1527,14 @@
 	int tmpScreenWidth, tmpScreenHeight;
 
 	// Temp vars to ensure we zoom to the LCD resolution or greater.
-	tmpScreenWidth = _screenWidth;
-	tmpScreenHeight = _screenHeight;
+	tmpScreenWidth = _videoMode.screenWidth;
+	tmpScreenHeight = _videoMode.screenHeight;
 
-	if (_screenHeight <= 240) {
+	if (_videoMode.screenHeight <= 240) {
 		tmpScreenHeight = 240;
 	}
 
-	if (_screenWidth <= 320) {
+	if (_videoMode.screenWidth <= 320) {
 		tmpScreenWidth = 320;
 	}
 
@@ -1447,17 +1542,17 @@
 	dst.y = _mouseCurState.y;
 
 	if (!_overlayVisible) {
-		scale = _scaleFactor;
-		width = _screenWidth;
-		height = _screenHeight;
+		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;
-		width = _overlayWidth;
-		height = _overlayHeight;
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
 		dst.w = _mouseCurState.rW;
 		dst.h = _mouseCurState.rH;
 		hotX = _mouseCurState.rHotX;
@@ -1479,7 +1574,7 @@
 		dst.y += _currentShakePos;
 	}
 
-	if (_adjustAspectRatio && !_overlayVisible)
+	if (_videoMode.aspectRatio && !_overlayVisible)
 		dst.y = real2Aspect(dst.y);
 
 	dst.x = scale * dst.x - _mouseCurState.rHotX;
@@ -1633,17 +1728,18 @@
 void OSystem_GP2X::handleScalerHotkeys(const SDL_KeyboardEvent &key) {
 	// Ctrl-Alt-a toggles aspect ratio correction
 	if (key.keysym.sym == 'a') {
-		setFeatureState(kFeatureAspectRatioCorrection, !_adjustAspectRatio);
-
+		beginGFXTransaction();
+			setFeatureState(kFeatureAspectRatioCorrection, !_videoMode.aspectRatio);
+		endGFXTransaction();
 		char buffer[128];
-		if (_adjustAspectRatio)
+		if (_videoMode.aspectRatio)
 			sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d",
-				_screenWidth, _screenHeight,
+				_videoMode.screenWidth, _videoMode.screenHeight,
 				_hwscreen->w, _hwscreen->h
 				);
 		else
 			sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d",
-				_screenWidth, _screenHeight,
+				_videoMode.screenWidth, _videoMode.screenHeight,
 				_hwscreen->w, _hwscreen->h
 				);
 		displayMessageOnOSD(buffer);
@@ -1653,7 +1749,7 @@
 	}
 
 	int newMode = -1;
-	int factor = _scaleFactor - 1;
+	int factor = _videoMode.scaleFactor - 1;
 
 	// Increase/decrease the scale factor
 	if (key.keysym.sym == SDLK_EQUALS || key.keysym.sym == SDLK_PLUS || key.keysym.sym == SDLK_MINUS ||
@@ -1679,13 +1775,15 @@
 	}
 
 	if (newMode >= 0) {
-		setGraphicsMode(newMode);
+		beginGFXTransaction();
+			setGraphicsMode(newMode);
+		endGFXTransaction();
 
 		if (_osdSurface) {
 			const char *newScalerName = 0;
 			const GraphicsMode *g = getSupportedGraphicsModes();
 			while (g->name) {
-				if (g->id == _mode) {
+				if (g->id == _videoMode.mode) {
 					newScalerName = g->description;
 					break;
 				}
@@ -1695,7 +1793,7 @@
 				char buffer[128];
 				sprintf(buffer, "Active graphics filter: %s\n%d x %d -> %d x %d",
 					newScalerName,
-					_screenWidth, _screenHeight,
+					_videoMode.screenWidth, _videoMode.screenHeight,
 					_hwscreen->w, _hwscreen->h
 					);
 				displayMessageOnOSD(buffer);


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the Scummvm-git-logs mailing list