[Scummvm-cvs-logs] SF.net SVN: scummvm:[45775] scummvm/trunk/backends/platform

aquadran at users.sourceforge.net aquadran at users.sourceforge.net
Mon Nov 9 15:29:55 CET 2009


Revision: 45775
          http://scummvm.svn.sourceforge.net/scummvm/?rev=45775&view=rev
Author:   aquadran
Date:     2009-11-09 14:29:53 +0000 (Mon, 09 Nov 2009)

Log Message:
-----------
added samsung tv backend

Added Paths:
-----------
    scummvm/trunk/backends/platform/samsungtv/
    scummvm/trunk/backends/platform/samsungtv/events.cpp
    scummvm/trunk/backends/platform/samsungtv/graphics.cpp
    scummvm/trunk/backends/platform/samsungtv/hardwarekeys.cpp
    scummvm/trunk/backends/platform/samsungtv/main.cpp
    scummvm/trunk/backends/platform/samsungtv/module.mk
    scummvm/trunk/backends/platform/samsungtv/sdl.cpp
    scummvm/trunk/backends/platform/samsungtv/sdl.h

Added: scummvm/trunk/backends/platform/samsungtv/events.cpp
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/events.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/events.cpp	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,358 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/events.cpp $
+ * $Id: events.cpp 43636 2009-08-22 12:35:49Z sev $
+ *
+ */
+
+#include "backends/platform/samsungtv/sdl.h"
+#include "common/util.h"
+#include "common/events.h"
+
+#if defined(SAMSUNGTV)
+
+static int mapKey(SDLKey key, SDLMod mod, Uint16 unicode) {
+	if (key >= SDLK_F1 && key <= SDLK_F9) {
+		return key - SDLK_F1 + Common::ASCII_F1;
+	} else if (key >= SDLK_KP0 && key <= SDLK_KP9) {
+		return key - SDLK_KP0 + '0';
+	} else if (key >= SDLK_UP && key <= SDLK_PAGEDOWN) {
+		return key;
+	} else if (unicode) {
+		return unicode;
+	} else if (key >= 'a' && key <= 'z' && (mod & KMOD_SHIFT)) {
+		return key & ~0x20;
+	} else if (key >= SDLK_NUMLOCK && key <= SDLK_EURO) {
+		return 0;
+	}
+	return key;
+}
+
+void OSystem_SDL_SamsungTV::fillMouseEvent(Common::Event &event, int x, int y) {
+	event.mouse.x = x;
+	event.mouse.y = y;
+
+	// Update the "keyboard mouse" coords
+	_km.x = x;
+	_km.y = y;
+
+	// Adjust for the screen scaling
+	if (!_overlayVisible) {
+		event.mouse.x /= _videoMode.scaleFactor;
+		event.mouse.y /= _videoMode.scaleFactor;
+		if (_videoMode.aspectRatioCorrection)
+			event.mouse.y = aspect2Real(event.mouse.y);
+	}
+}
+
+void OSystem_SDL_SamsungTV::handleKbdMouse() {
+	uint32 curTime = getMillis();
+	if (curTime >= _km.last_time + _km.delay_time) {
+		_km.last_time = curTime;
+		if (_km.x_down_count == 1) {
+			_km.x_down_time = curTime;
+			_km.x_down_count = 2;
+		}
+		if (_km.y_down_count == 1) {
+			_km.y_down_time = curTime;
+			_km.y_down_count = 2;
+		}
+
+		if (_km.x_vel || _km.y_vel) {
+			if (_km.x_down_count) {
+				if (curTime > _km.x_down_time + _km.delay_time * 12) {
+					if (_km.x_vel > 0)
+						_km.x_vel++;
+					else
+						_km.x_vel--;
+				} else if (curTime > _km.x_down_time + _km.delay_time * 8) {
+					if (_km.x_vel > 0)
+						_km.x_vel = 5;
+					else
+						_km.x_vel = -5;
+				}
+			}
+			if (_km.y_down_count) {
+				if (curTime > _km.y_down_time + _km.delay_time * 12) {
+					if (_km.y_vel > 0)
+						_km.y_vel++;
+					else
+						_km.y_vel--;
+				} else if (curTime > _km.y_down_time + _km.delay_time * 8) {
+					if (_km.y_vel > 0)
+						_km.y_vel = 5;
+					else
+						_km.y_vel = -5;
+				}
+			}
+
+			_km.x += _km.x_vel;
+			_km.y += _km.y_vel;
+
+			if (_km.x < 0) {
+				_km.x = 0;
+				_km.x_vel = -1;
+				_km.x_down_count = 1;
+			} else if (_km.x > _km.x_max) {
+				_km.x = _km.x_max;
+				_km.x_vel = 1;
+				_km.x_down_count = 1;
+			}
+
+			if (_km.y < 0) {
+				_km.y = 0;
+				_km.y_vel = -1;
+				_km.y_down_count = 1;
+			} else if (_km.y > _km.y_max) {
+				_km.y = _km.y_max;
+				_km.y_vel = 1;
+				_km.y_down_count = 1;
+			}
+
+			setMousePos(_km.x, _km.y);
+		}
+	}
+}
+
+static byte SDLModToOSystemKeyFlags(SDLMod mod) {
+	byte b = 0;
+
+	if (mod & KMOD_SHIFT)
+		b |= Common::KBD_SHIFT;
+	if (mod & KMOD_ALT)
+		b |= Common::KBD_ALT;
+	if (mod & KMOD_CTRL)
+		b |= Common::KBD_CTRL;
+
+	return b;
+}
+
+bool OSystem_SDL_SamsungTV::pollEvent(Common::Event &event) {
+	SDL_Event ev;
+	byte b = 0;
+
+	handleKbdMouse();
+
+	// If the screen mode changed, send an Common::EVENT_SCREEN_CHANGED
+	if (_modeChanged) {
+		_modeChanged = false;
+		event.type = Common::EVENT_SCREEN_CHANGED;
+		return true;
+	}
+
+	while (SDL_PollEvent(&ev)) {
+		preprocessEvents(&ev);
+
+		switch (ev.type) {
+		case SDL_KEYDOWN:{
+			if (ev.key.keysym.sym == SDLK_UP) {
+				_km.y_vel = -1;
+				_km.y_down_count = 1;
+				event.type = Common::EVENT_MOUSEMOVE;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_DOWN) {
+				_km.y_vel = 1;
+				_km.y_down_count = 1;
+				event.type = Common::EVENT_MOUSEMOVE;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_LEFT) {
+				_km.x_vel = -1;
+				_km.x_down_count = 1;
+				event.type = Common::EVENT_MOUSEMOVE;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_RIGHT) {
+				_km.x_vel = 1;
+				_km.x_down_count = 1;
+				event.type = Common::EVENT_MOUSEMOVE;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_z) {
+				event.type = Common::EVENT_LBUTTONDOWN;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_HOME) {
+				event.type = Common::EVENT_RBUTTONDOWN;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_F4) {
+				event.type = Common::EVENT_KEYDOWN;
+				event.kbd.keycode = Common::KEYCODE_SPACE;
+				event.kbd.ascii = ' ';
+				return true;
+			}
+
+			b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
+
+			// Alt-S: Create a screenshot
+			if (b == Common::KBD_ALT && ev.key.keysym.sym == 's') {
+				char filename[20];
+
+				for (int n = 0;; n++) {
+					SDL_RWops *file;
+
+					sprintf(filename, "scummvm%05d.bmp", n);
+					file = SDL_RWFromFile(filename, "r");
+					if (!file)
+						break;
+					SDL_RWclose(file);
+				}
+				if (saveScreenshot(filename))
+					printf("Saved '%s'\n", filename);
+				else
+					printf("Could not save screenshot!\n");
+				break;
+			}
+
+			// On other unices, Control-Q quits
+			if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'q') {
+				event.type = Common::EVENT_QUIT;
+				return true;
+			}
+
+			if ((ev.key.keysym.mod & KMOD_CTRL) && ev.key.keysym.sym == 'u') {
+				event.type = Common::EVENT_MUTE;
+				return true;
+			}
+
+			// Ctrl-Alt-<key> will change the GFX mode
+			if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
+
+				handleScalerHotkeys(ev.key);
+				break;
+			}
+			const bool event_complete = remapKey(ev, event);
+
+			if (event_complete)
+				return true;
+
+			event.type = Common::EVENT_KEYDOWN;
+			event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+			event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
+
+			return true;
+			}
+		case SDL_KEYUP:
+			{
+			if (ev.key.keysym.sym == SDLK_UP || ev.key.keysym.sym == SDLK_DOWN || ev.key.keysym.sym == SDLK_LEFT || ev.key.keysym.sym == SDLK_RIGHT) {
+				_km.x_vel = 0;
+				_km.x_down_count = 0;
+				_km.y_vel = 0;
+				_km.y_down_count = 0;
+				event.type = Common::EVENT_MOUSEMOVE;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_z) {
+				event.type = Common::EVENT_LBUTTONUP;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_HOME) {
+				event.type = Common::EVENT_RBUTTONUP;
+				fillMouseEvent(event, _km.x, _km.y);
+				return true;
+			} else if (ev.key.keysym.sym == SDLK_F4) {
+				event.type = Common::EVENT_KEYUP;
+				event.kbd.keycode = Common::KEYCODE_SPACE;
+				event.kbd.ascii = ' ';
+				return true;
+			}
+
+			const bool event_complete = remapKey(ev,event);
+
+			if (event_complete)
+				return true;
+
+			event.type = Common::EVENT_KEYUP;
+			event.kbd.keycode = (Common::KeyCode)ev.key.keysym.sym;
+			event.kbd.ascii = mapKey(ev.key.keysym.sym, ev.key.keysym.mod, ev.key.keysym.unicode);
+			b = event.kbd.flags = SDLModToOSystemKeyFlags(SDL_GetModState());
+
+			// Ctrl-Alt-<key> will change the GFX mode
+			if ((b & (Common::KBD_CTRL|Common::KBD_ALT)) == (Common::KBD_CTRL|Common::KBD_ALT)) {
+				// Swallow these key up events
+				break;
+			}
+
+			return true;
+			}
+		case SDL_MOUSEMOTION:
+			event.type = Common::EVENT_MOUSEMOVE;
+			fillMouseEvent(event, ev.motion.x, ev.motion.y);
+
+			setMousePos(event.mouse.x, event.mouse.y);
+			return true;
+
+		case SDL_MOUSEBUTTONDOWN:
+			if (ev.button.button == SDL_BUTTON_LEFT)
+				event.type = Common::EVENT_LBUTTONDOWN;
+			else if (ev.button.button == SDL_BUTTON_RIGHT)
+				event.type = Common::EVENT_RBUTTONDOWN;
+#if defined(SDL_BUTTON_WHEELUP) && defined(SDL_BUTTON_WHEELDOWN)
+			else if (ev.button.button == SDL_BUTTON_WHEELUP)
+				event.type = Common::EVENT_WHEELUP;
+			else if (ev.button.button == SDL_BUTTON_WHEELDOWN)
+				event.type = Common::EVENT_WHEELDOWN;
+#endif
+#if defined(SDL_BUTTON_MIDDLE)
+			else if (ev.button.button == SDL_BUTTON_MIDDLE)
+				event.type = Common::EVENT_MBUTTONDOWN;
+#endif
+			else
+				break;
+
+			fillMouseEvent(event, ev.button.x, ev.button.y);
+
+			return true;
+
+		case SDL_MOUSEBUTTONUP:
+			if (ev.button.button == SDL_BUTTON_LEFT)
+				event.type = Common::EVENT_LBUTTONUP;
+			else if (ev.button.button == SDL_BUTTON_RIGHT)
+				event.type = Common::EVENT_RBUTTONUP;
+#if defined(SDL_BUTTON_MIDDLE)
+			else if (ev.button.button == SDL_BUTTON_MIDDLE)
+				event.type = Common::EVENT_MBUTTONUP;
+#endif
+			else
+				break;
+			fillMouseEvent(event, ev.button.x, ev.button.y);
+
+			return true;
+
+		case SDL_VIDEOEXPOSE:
+			_forceFull = true;
+			break;
+
+		case SDL_QUIT:
+			event.type = Common::EVENT_QUIT;
+			return true;
+		}
+	}
+	return false;
+}
+
+bool OSystem_SDL_SamsungTV::remapKey(SDL_Event &ev, Common::Event &event) {
+	return false;
+}
+
+#endif


Property changes on: scummvm/trunk/backends/platform/samsungtv/events.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/graphics.cpp
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/graphics.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/graphics.cpp	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,1831 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/graphics.cpp $
+ * $Id: graphics.cpp 44495 2009-09-30 16:16:53Z fingolfin $
+ *
+ */
+
+#include "backends/platform/samsungtv/sdl.h"
+#include "common/mutex.h"
+#include "common/util.h"
+#include "common/list.h"
+#include "graphics/font.h"
+#include "graphics/fontman.h"
+#include "graphics/scaler.h"
+#include "graphics/surface.h"
+
+#if defined(SAMSUNGTV)
+
+static const OSystem::GraphicsMode s_supportedGraphicsModes[] = {
+	{"1x", "Normal (no scaling)", GFX_NORMAL},
+	{"2x", "2x", GFX_DOUBLESIZE},
+	{"3x", "3x", GFX_TRIPLESIZE},
+	{"2xsai", "2xSAI", GFX_2XSAI},
+	{"super2xsai", "Super2xSAI", GFX_SUPER2XSAI},
+	{"supereagle", "SuperEagle", GFX_SUPEREAGLE},
+	{"advmame2x", "AdvMAME2x", GFX_ADVMAME2X},
+	{"advmame3x", "AdvMAME3x", GFX_ADVMAME3X},
+	{"tv2x", "TV2x", GFX_TV2X},
+	{"dotmatrix", "DotMatrix", GFX_DOTMATRIX},
+	{0, 0, 0}
+};
+
+// Table of relative scalers magnitudes
+// [definedScale - 1][scaleFactor - 1]
+static ScalerProc *scalersMagn[3][3] = {
+#ifndef DISABLE_SCALERS
+	{ Normal1x, AdvMame2x, AdvMame3x },
+	{ Normal1x, Normal1x, Normal1o5x },
+	{ Normal1x, Normal1x, Normal1x }
+#else // remove dependencies on other scalers
+	{ Normal1x, Normal1x, Normal1x },
+	{ Normal1x, Normal1x, Normal1x },
+	{ Normal1x, Normal1x, Normal1x }
+#endif
+};
+
+static const int s_gfxModeSwitchTable[][4] = {
+		{ GFX_NORMAL, GFX_DOUBLESIZE, GFX_TRIPLESIZE, -1 },
+		{ GFX_NORMAL, GFX_ADVMAME2X, GFX_ADVMAME3X, -1 },
+		{ GFX_NORMAL, GFX_HQ2X, GFX_HQ3X, -1 },
+		{ GFX_NORMAL, GFX_2XSAI, -1, -1 },
+		{ GFX_NORMAL, GFX_SUPER2XSAI, -1, -1 },
+		{ GFX_NORMAL, GFX_SUPEREAGLE, -1, -1 },
+		{ GFX_NORMAL, GFX_TV2X, -1, -1 },
+		{ GFX_NORMAL, GFX_DOTMATRIX, -1, -1 }
+	};
+
+#ifndef DISABLE_SCALERS
+static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
+#endif
+
+const OSystem::GraphicsMode *OSystem_SDL_SamsungTV::getSupportedGraphicsModes() const {
+	return s_supportedGraphicsModes;
+}
+
+int OSystem_SDL_SamsungTV::getDefaultGraphicsMode() const {
+	return GFX_2XSAI;
+}
+
+void OSystem_SDL_SamsungTV::beginGFXTransaction(void) {
+	assert(_transactionMode == kTransactionNone);
+
+	_transactionMode = kTransactionActive;
+
+	_transactionDetails.sizeChanged = false;
+
+	_transactionDetails.needHotswap = false;
+	_transactionDetails.needUpdatescreen = false;
+
+	_transactionDetails.normal1xScaler = false;
+	_transactionDetails.formatChanged = false;
+
+	_oldVideoMode = _videoMode;
+}
+
+OSystem::TransactionError OSystem_SDL_SamsungTV::endGFXTransaction(void) {
+	int errors = kTransactionSuccess;
+
+	assert(_transactionMode != kTransactionNone);
+
+	if (_transactionMode == kTransactionRollback) {
+		if (_videoMode.fullscreen != _oldVideoMode.fullscreen) {
+			errors |= kTransactionFullscreenFailed;
+
+			_videoMode.fullscreen = _oldVideoMode.fullscreen;
+		} else if (_videoMode.aspectRatioCorrection != _oldVideoMode.aspectRatioCorrection) {
+			errors |= kTransactionAspectRatioFailed;
+
+			_videoMode.aspectRatioCorrection = _oldVideoMode.aspectRatioCorrection;
+		} else if (_videoMode.mode != _oldVideoMode.mode) {
+			errors |= kTransactionModeSwitchFailed;
+
+			_videoMode.mode = _oldVideoMode.mode;
+			_videoMode.scaleFactor = _oldVideoMode.scaleFactor;
+		} else if (_videoMode.format != _oldVideoMode.format) {
+			errors |= kTransactionFormatNotSupported;
+
+			_videoMode.format = _oldVideoMode.format;
+			_screenFormat = _videoMode.format;
+		} 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.aspectRatioCorrection == _oldVideoMode.aspectRatioCorrection &&
+			_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 || _transactionDetails.formatChanged) {
+		unloadGFXMode();
+		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();
+	} 
+
+	_transactionMode = kTransactionNone;
+	return (TransactionError)errors;
+}
+
+Common::List<Graphics::PixelFormat> OSystem_SDL_SamsungTV::getSupportedFormats() {
+	static Common::List<Graphics::PixelFormat>list;
+	list.push_back(Graphics::PixelFormat(2, 5, 6, 5, 0, 11, 5, 0, 0));
+	list.push_back(Graphics::PixelFormat::createFormatCLUT8());
+	return list;
+}
+
+bool OSystem_SDL_SamsungTV::setGraphicsMode(int mode) {
+	Common::StackLock lock(_graphicsMutex);
+
+	assert(_transactionMode == kTransactionActive);
+
+	if (_oldVideoMode.setup && _oldVideoMode.mode == mode)
+		return true;
+
+	int newScaleFactor = 1;
+
+	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;
+	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;
+
+	_transactionDetails.needUpdatescreen = true;
+
+	_videoMode.mode = mode;
+	_videoMode.scaleFactor = newScaleFactor;
+
+	return true;
+}
+
+void OSystem_SDL_SamsungTV::setGraphicsModeIntern() {
+	Common::StackLock lock(_graphicsMutex);
+	ScalerProc *newScalerProc = 0;
+
+	switch (_videoMode.mode) {
+	case GFX_NORMAL:
+		newScalerProc = Normal1x;
+		break;
+#ifndef DISABLE_SCALERS
+	case GFX_DOUBLESIZE:
+		newScalerProc = Normal2x;
+		break;
+	case GFX_TRIPLESIZE:
+		newScalerProc = Normal3x;
+		break;
+	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;
+	case GFX_TV2X:
+		newScalerProc = TV2x;
+		break;
+	case GFX_DOTMATRIX:
+		newScalerProc = DotMatrix;
+		break;
+#endif // DISABLE_SCALERS
+
+	default:
+		error("Unknown gfx mode %d", _videoMode.mode);
+	}
+
+	_scalerProc = newScalerProc;
+
+	if (_videoMode.mode != GFX_NORMAL) {
+		for (int i = 0; i < ARRAYSIZE(s_gfxModeSwitchTable); i++) {
+			if (s_gfxModeSwitchTable[i][1] == _videoMode.mode || s_gfxModeSwitchTable[i][2] == _videoMode.mode) {
+				_scalerType = i;
+				break;
+			}
+		}
+	}
+
+	if (!_screen || !_hwscreen || !_prehwscreen)
+		return;
+
+	// Blit everything to the screen
+	_forceFull = true;
+
+	// Even if the old and new scale factors are the same, we may have a
+	// different scaler for the cursor now.
+	blitCursor();
+}
+
+int OSystem_SDL_SamsungTV::getGraphicsMode() const {
+	assert (_transactionMode == kTransactionNone);
+	return _videoMode.mode;
+}
+
+void OSystem_SDL_SamsungTV::initSize(uint w, uint h, const Graphics::PixelFormat *format) {
+	assert(_transactionMode == kTransactionActive);
+
+	//avoid redundant format changes
+	Graphics::PixelFormat newFormat;
+	if (!format)
+		newFormat = Graphics::PixelFormat::createFormatCLUT8();
+	else
+		newFormat = *format;
+
+	assert(newFormat.bytesPerPixel > 0);
+
+	if (newFormat != _videoMode.format)
+	{
+		_videoMode.format = newFormat;
+		_transactionDetails.formatChanged = true;
+		_screenFormat = newFormat;
+	}
+
+	// Avoid redundant res changes
+	if ((int)w == _videoMode.screenWidth && (int)h == _videoMode.screenHeight)
+		return;
+
+	_videoMode.screenWidth = w;
+	_videoMode.screenHeight = h;
+
+	_cksumNum = (w * h / (8 * 8));
+
+	_transactionDetails.sizeChanged = true;
+
+	free(_dirtyChecksums);
+	_dirtyChecksums = (uint32 *)calloc(_cksumNum * 2, sizeof(uint32));
+}
+
+
+static void fixupResolutionForAspectRatio(AspectRatio desiredAspectRatio, int &width, int &height) {
+	assert(&width != &height);
+
+	if (desiredAspectRatio.isAuto())
+		return;
+	
+	int kw = desiredAspectRatio.kw();
+	int kh = desiredAspectRatio.kh();
+
+	const int w = width;
+	const int h = height;
+
+	SDL_Rect const* const*availableModes = SDL_ListModes(NULL, SDL_FULLSCREEN|SDL_SWSURFACE); //TODO : Maybe specify a pixel format
+	assert(availableModes);
+
+	const SDL_Rect *bestMode = NULL;
+	uint bestMetric = (uint)-1; // Metric is wasted space
+	while (const SDL_Rect *mode = *availableModes++) {
+		if (mode->w < w)
+			continue;
+		if (mode->h < h)
+			continue;
+		if (mode->h * kw != mode->w * kh)
+			continue;
+		//printf("%d %d\n", mode->w, mode->h);
+
+		uint metric = mode->w * mode->h - w * h;
+		if (metric > bestMetric)
+			continue;
+
+		bestMetric = metric;
+		bestMode = mode;
+	}
+
+	if (!bestMode) {
+		warning("Unable to enforce the desired aspect ratio!");
+		return;
+	}
+	//printf("%d %d\n", bestMode->w, bestMode->h);
+	width = bestMode->w;
+	height = bestMode->h;
+}
+
+bool OSystem_SDL_SamsungTV::loadGFXMode() {
+	assert(_inited);
+	_forceFull = true;
+
+	_videoMode.overlayWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+	_videoMode.overlayHeight = _videoMode.screenHeight * _videoMode.scaleFactor;
+
+	if (_videoMode.screenHeight != 200 && _videoMode.screenHeight != 400)
+		_videoMode.aspectRatioCorrection = false;
+
+	if (_videoMode.aspectRatioCorrection)
+		_videoMode.overlayHeight = real2Aspect(_videoMode.overlayHeight);
+
+	_videoMode.hardwareWidth = _videoMode.screenWidth * _videoMode.scaleFactor;
+	_videoMode.hardwareHeight = effectiveScreenHeight();
+
+	_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");
+
+	//
+	// Create the surface that contains the scaled graphics in 16 bit mode
+	//
+
+	if (_videoMode.fullscreen) {
+		fixupResolutionForAspectRatio(_videoMode.desiredAspectRatio, _videoMode.hardwareWidth, _videoMode.hardwareHeight);
+	}
+
+	_hwscreen = SDL_SetVideoMode(_videoMode.hardwareWidth, _videoMode.hardwareHeight, 32, SDL_FULLSCREEN | SDL_HWSURFACE);
+
+	if (_hwscreen == NULL) {
+		// DON'T use error(), as this tries to bring up the debug
+		// console, which WON'T WORK now that _hwscreen is hosed.
+
+		if (!_oldVideoMode.setup) {
+			warning("SDL_SetVideoMode says we can't switch to that mode (%s)", SDL_GetError());
+			quit();
+		} else {
+			return false;
+		}
+	}
+
+	_prehwscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.hardwareWidth, _videoMode.hardwareHeight,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+	if (_prehwscreen == NULL)
+		error("allocating _prehwscreen failed");
+
+	//
+	// Create the surface used for the graphics in 16 bit before scaling, and also the overlay
+	//
+
+	// Need some extra bytes around when using 2xSaI
+	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.screenWidth + 3, _videoMode.screenHeight + 3,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+
+	if (_tmpscreen == NULL)
+		error("allocating _tmpscreen failed");
+
+	_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth, _videoMode.overlayHeight,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+
+	if (_overlayscreen == NULL)
+		error("allocating _overlayscreen failed");
+
+	_overlayFormat.bytesPerPixel = _overlayscreen->format->BytesPerPixel;
+
+	_overlayFormat.rLoss = _overlayscreen->format->Rloss;
+	_overlayFormat.gLoss = _overlayscreen->format->Gloss;
+	_overlayFormat.bLoss = _overlayscreen->format->Bloss;
+	_overlayFormat.aLoss = _overlayscreen->format->Aloss;
+
+	_overlayFormat.rShift = _overlayscreen->format->Rshift;
+	_overlayFormat.gShift = _overlayscreen->format->Gshift;
+	_overlayFormat.bShift = _overlayscreen->format->Bshift;
+	_overlayFormat.aShift = _overlayscreen->format->Ashift;
+
+	_tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, _videoMode.overlayWidth + 3, _videoMode.overlayHeight + 3,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+
+	if (_tmpscreen2 == NULL)
+		error("allocating _tmpscreen2 failed");
+
+#ifdef USE_OSD
+	_osdSurface = SDL_CreateRGBSurface(SDL_HWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_hwscreen->w,
+						_hwscreen->h,
+						32,
+						_hwscreen->format->Rmask,
+						_hwscreen->format->Gmask,
+						_hwscreen->format->Bmask,
+						_hwscreen->format->Amask);
+	if (_osdSurface == NULL)
+		error("allocating _osdSurface failed");
+	SDL_SetColorKey(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOSDColorKey);
+#endif
+
+	// keyboard cursor control, some other better place for it?
+	_km.x_max = _videoMode.screenWidth * _videoMode.scaleFactor - 1;
+	_km.y_max = effectiveScreenHeight() - 1;
+	_km.delay_time = 25;
+	_km.last_time = 0;
+
+	InitScalers(565);
+
+	return true;
+}
+
+void OSystem_SDL_SamsungTV::unloadGFXMode() {
+	if (_screen) {
+		SDL_FreeSurface(_screen);
+		_screen = NULL;
+	}
+
+	if (_hwscreen) {
+		SDL_FreeSurface(_hwscreen);
+		_hwscreen = NULL;
+	}
+
+	if (_prehwscreen) {
+		SDL_FreeSurface(_prehwscreen);
+		_prehwscreen = NULL;
+	}
+
+	if (_tmpscreen) {
+		SDL_FreeSurface(_tmpscreen);
+		_tmpscreen = NULL;
+	}
+
+	if (_tmpscreen2) {
+		SDL_FreeSurface(_tmpscreen2);
+		_tmpscreen2 = NULL;
+	}
+
+	if (_overlayscreen) {
+		SDL_FreeSurface(_overlayscreen);
+		_overlayscreen = NULL;
+	}
+
+#ifdef USE_OSD
+	if (_osdSurface) {
+		SDL_FreeSurface(_osdSurface);
+		_osdSurface = NULL;
+	}
+#endif
+	DestroyScalers();
+}
+
+bool OSystem_SDL_SamsungTV::hotswapGFXMode() {
+	if (!_screen)
+		return false;
+
+	// Keep around the old _screen & _overlayscreen so we can restore the screen data
+	// after the mode switch.
+	SDL_Surface *old_screen = _screen;
+	_screen = NULL;
+	SDL_Surface *old_overlayscreen = _overlayscreen;
+	_overlayscreen = NULL;
+
+	// Release the HW screen surface
+	SDL_FreeSurface(_hwscreen); _hwscreen = NULL;
+
+	SDL_FreeSurface(_prehwscreen); _prehwscreen = NULL;
+
+	SDL_FreeSurface(_tmpscreen); _tmpscreen = NULL;
+	SDL_FreeSurface(_tmpscreen2); _tmpscreen2 = NULL;
+
+#ifdef USE_OSD
+	// Release the OSD surface
+	SDL_FreeSurface(_osdSurface); _osdSurface = NULL;
+#endif
+
+	// Setup the new GFX mode
+	if (!loadGFXMode()) {
+		unloadGFXMode();
+
+		_screen = old_screen;
+		_overlayscreen = old_overlayscreen;
+
+		return false;
+	}
+
+	// reset palette
+	SDL_SetColors(_screen, _currentPalette, 0, 256);
+
+	// Restore old screen content
+	SDL_BlitSurface(old_screen, NULL, _screen, NULL);
+	SDL_BlitSurface(old_overlayscreen, NULL, _overlayscreen, NULL);
+
+	// Free the old surfaces
+	SDL_FreeSurface(old_screen);
+	SDL_FreeSurface(old_overlayscreen);
+
+	// Update cursor to new scale
+	blitCursor();
+
+	// Blit everything to the screen
+	internUpdateScreen();
+
+	return true;
+}
+
+void OSystem_SDL_SamsungTV::updateScreen() {
+	assert (_transactionMode == kTransactionNone);
+
+	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
+
+	internUpdateScreen();
+}
+
+void OSystem_SDL_SamsungTV::internUpdateScreen() {
+	SDL_Surface *srcSurf, *origSurf;
+	int height, width;
+	ScalerProc *scalerProc;
+	int scale1;
+
+	// If the shake position changed, fill the dirty area with blackness
+	if (_currentShakePos != _newShakePos) {
+		SDL_Rect blackrect = {0, 0, _videoMode.screenWidth * _videoMode.scaleFactor, _newShakePos * _videoMode.scaleFactor};
+
+		if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+			blackrect.h = real2Aspect(blackrect.h - 1) + 1;
+
+		SDL_FillRect(_prehwscreen, &blackrect, 0);
+
+		_currentShakePos = _newShakePos;
+
+		_forceFull = true;
+	}
+
+	// Check whether the palette was changed in the meantime and update the
+	// screen surface accordingly.
+	if (_screen && _paletteDirtyEnd != 0) {
+		SDL_SetColors(_screen, _currentPalette + _paletteDirtyStart,
+			_paletteDirtyStart,
+			_paletteDirtyEnd - _paletteDirtyStart);
+
+		_paletteDirtyEnd = 0;
+
+		_forceFull = true;
+	}
+
+#ifdef USE_OSD
+	// OSD visible (i.e. non-transparent)?
+	if (_osdAlpha != SDL_ALPHA_TRANSPARENT) {
+		// Updated alpha value
+		const int diff = SDL_GetTicks() - _osdFadeStartTime;
+		if (diff > 0) {
+			if (diff >= kOSDFadeOutDuration) {
+				// Back to full transparency
+				_osdAlpha = SDL_ALPHA_TRANSPARENT;
+			} else {
+				// Do a linear fade out...
+				const int startAlpha = SDL_ALPHA_TRANSPARENT + kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
+				_osdAlpha = startAlpha + diff * (SDL_ALPHA_TRANSPARENT - startAlpha) / kOSDFadeOutDuration;
+			}
+			SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
+			_forceFull = true;
+		}
+	}
+#endif
+
+	if (!_overlayVisible) {
+		origSurf = _screen;
+		srcSurf = _tmpscreen;
+		width = _videoMode.screenWidth;
+		height = _videoMode.screenHeight;
+		scalerProc = _scalerProc;
+		scale1 = _videoMode.scaleFactor;
+	} else {
+		origSurf = _overlayscreen;
+		srcSurf = _tmpscreen2;
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
+		scalerProc = Normal1x;
+
+		scale1 = 1;
+	}
+
+	// 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;
+		uint32 srcPitch, dstPitch;
+		SDL_Rect *lastRect = _dirtyRectList + _numDirtyRects;
+
+		for (r = _dirtyRectList; r != lastRect; ++r) {
+			dst = *r;
+			dst.x++;	// Shift rect by one since 2xSai needs to access the data around
+			dst.y++;	// any pixel to scale it, and we want to avoid mem access crashes.
+
+			if (SDL_BlitSurface(origSurf, r, srcSurf, &dst) != 0)
+				error("SDL_BlitSurface failed: %s", SDL_GetError());
+		}
+
+		SDL_LockSurface(srcSurf);
+		SDL_LockSurface(_prehwscreen);
+
+		srcPitch = srcSurf->pitch;
+		dstPitch = _prehwscreen->pitch;
+
+		for (r = _dirtyRectList; r != lastRect; ++r) {
+			register int dst_y = r->y + _currentShakePos;
+			register int dst_h = 0;
+			register int orig_dst_y = 0;
+			register int rx1 = r->x * scale1;
+
+			if (dst_y < height) {
+				dst_h = r->h;
+				if (dst_h > height - dst_y)
+					dst_h = height - dst_y;
+
+				orig_dst_y = dst_y;
+				dst_y = dst_y * scale1;
+
+				if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+					dst_y = real2Aspect(dst_y);
+
+				assert(scalerProc != NULL);
+				scalerProc((byte *)srcSurf->pixels + (r->x * 2 + 2) + (r->y + 1) * srcPitch, srcPitch,
+						   (byte *)_prehwscreen->pixels + rx1 * 2 + dst_y * dstPitch, dstPitch, r->w, dst_h);
+			}
+
+			r->x = rx1;
+			r->y = dst_y;
+			r->w = r->w * scale1;
+			r->h = dst_h * scale1;
+
+#ifndef DISABLE_SCALERS
+			if (_videoMode.aspectRatioCorrection && orig_dst_y < height && !_overlayVisible)
+				r->h = stretch200To240((uint8 *)_prehwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y * scale1);
+#endif
+		}
+		SDL_UnlockSurface(srcSurf);
+		SDL_UnlockSurface(_prehwscreen);
+
+		// 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, _prehwscreen, 0);
+		}
+#endif
+		// Finally, blit all our changes to the screen
+		SDL_UpdateRects(_prehwscreen, _numDirtyRects, _dirtyRectList);
+	}
+
+	SDL_BlitSurface(_prehwscreen, 0, _hwscreen, 0);
+	SDL_UpdateRect(_hwscreen, 0, 0, _hwscreen->w, _hwscreen->h);
+
+	_numDirtyRects = 0;
+	_forceFull = false;
+	_mouseNeedsRedraw = false;
+}
+
+bool OSystem_SDL_SamsungTV::saveScreenshot(const char *filename) {
+	assert(_hwscreen != NULL);
+
+	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
+	return SDL_SaveBMP(_hwscreen, filename) == 0;
+}
+
+void OSystem_SDL_SamsungTV::setFullscreenMode(bool enable) {
+	Common::StackLock lock(_graphicsMutex);
+
+	if (_oldVideoMode.setup && _oldVideoMode.fullscreen == enable)
+		return;
+
+	if (_transactionMode == kTransactionActive) {
+		_videoMode.fullscreen = enable;
+		_transactionDetails.needHotswap = true;
+	}
+}
+
+void OSystem_SDL_SamsungTV::setAspectRatioCorrection(bool enable) {
+	Common::StackLock lock(_graphicsMutex);
+
+	if (_oldVideoMode.setup && _oldVideoMode.aspectRatioCorrection == enable)
+		return;
+
+	if (_transactionMode == kTransactionActive) {
+		_videoMode.aspectRatioCorrection = enable;
+		_transactionDetails.needHotswap = true;
+	}
+}
+
+void OSystem_SDL_SamsungTV::copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h) {
+	assert (_transactionMode == kTransactionNone);
+	assert(src);
+
+	if (_screen == NULL) {
+		warning("OSystem_SDL::copyRectToScreen: _screen == NULL");
+		return;
+	}
+
+	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
+
+	assert(x >= 0 && x < _videoMode.screenWidth);
+	assert(y >= 0 && y < _videoMode.screenHeight);
+	assert(h > 0 && y + h <= _videoMode.screenHeight);
+	assert(w > 0 && x + w <= _videoMode.screenWidth);
+
+	if (IS_ALIGNED(src, 4) && pitch == _videoMode.screenWidth && x == 0 && y == 0 &&
+			w == _videoMode.screenWidth && h == _videoMode.screenHeight && _modeFlags & DF_WANT_RECT_OPTIM) {
+		/* Special, optimized case for full screen updates.
+		 * It tries to determine what areas were actually changed,
+		 * and just updates those, on the actual display. */
+		addDirtyRgnAuto(src);
+	} else {
+		_cksumValid = false;
+		addDirtyRect(x, y, w, h);
+	}
+
+	// Try to lock the screen surface
+	if (SDL_LockSurface(_screen) == -1)
+		error("SDL_LockSurface failed: %s", SDL_GetError());
+
+	byte *dst = (byte *)_screen->pixels + y * _videoMode.screenWidth * _screenFormat.bytesPerPixel + x * _screenFormat.bytesPerPixel;
+	if (_videoMode.screenWidth == w && pitch == w * _screenFormat.bytesPerPixel) {
+		memcpy(dst, src, h*w*_screenFormat.bytesPerPixel);
+	} else {
+		do {
+			memcpy(dst, src, w * _screenFormat.bytesPerPixel);
+			src += pitch;
+			dst += _videoMode.screenWidth * _screenFormat.bytesPerPixel;
+		} while (--h);
+	}
+
+	// Unlock the screen surface
+	SDL_UnlockSurface(_screen);
+}
+
+Graphics::Surface *OSystem_SDL_SamsungTV::lockScreen() {
+	assert (_transactionMode == kTransactionNone);
+
+	// Lock the graphics mutex
+	lockMutex(_graphicsMutex);
+
+	// paranoia check
+	assert(!_screenIsLocked);
+	_screenIsLocked = true;
+
+	// Try to lock the screen surface
+	if (SDL_LockSurface(_screen) == -1)
+		error("SDL_LockSurface failed: %s", SDL_GetError());
+
+	_framebuffer.pixels = _screen->pixels;
+	_framebuffer.w = _screen->w;
+	_framebuffer.h = _screen->h;
+	_framebuffer.pitch = _screen->pitch;
+	_framebuffer.bytesPerPixel = _screenFormat.bytesPerPixel;
+
+	return &_framebuffer;
+}
+
+void OSystem_SDL_SamsungTV::unlockScreen() {
+	assert (_transactionMode == kTransactionNone);
+
+	// paranoia check
+	assert(_screenIsLocked);
+	_screenIsLocked = false;
+
+	// Unlock the screen surface
+	SDL_UnlockSurface(_screen);
+
+	// Trigger a full screen update
+	_forceFull = true;
+
+	// Finally unlock the graphics mutex
+	unlockMutex(_graphicsMutex);
+}
+
+void OSystem_SDL_SamsungTV::addDirtyRect(int x, int y, int w, int h, bool realCoordinates) {
+	if (_forceFull)
+		return;
+
+	if (_numDirtyRects == NUM_DIRTY_RECT) {
+		_forceFull = true;
+		return;
+	}
+
+	int height, width;
+
+	if (!_overlayVisible && !realCoordinates) {
+		width = _videoMode.screenWidth;
+		height = _videoMode.screenHeight;
+	} else {
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
+	}
+
+	// Extend the dirty region by 1 pixel for scalers
+	// that "smear" the screen, e.g. 2xSAI
+	if (!realCoordinates) {
+		x--;
+		y--;
+		w+=2;
+		h+=2;
+	}
+
+	// clip
+	if (x < 0) {
+		w += x;
+		x = 0;
+	}
+
+	if (y < 0) {
+		h += y;
+		y=0;
+	}
+
+	if (w > width - x) {
+		w = width - x;
+	}
+
+	if (h > height - y) {
+		h = height - y;
+	}
+
+#ifndef DISABLE_SCALERS
+	if (_videoMode.aspectRatioCorrection && !_overlayVisible && !realCoordinates) {
+		makeRectStretchable(x, y, w, h);
+	}
+#endif
+
+	if (w == width && h == height) {
+		_forceFull = true;
+		return;
+	}
+
+	if (w > 0 && h > 0) {
+		SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];
+
+		r->x = x;
+		r->y = y;
+		r->w = w;
+		r->h = h;
+	}
+}
+
+
+void OSystem_SDL_SamsungTV::makeChecksums(const byte *buf) {
+	assert(buf);
+	uint32 *sums = _dirtyChecksums;
+	uint x,y;
+	const uint last_x = (uint)_videoMode.screenWidth / 8;
+	const uint last_y = (uint)_videoMode.screenHeight / 8;
+
+	const uint BASE = 65521; /* largest prime smaller than 65536 */
+
+	/* the 8x8 blocks in buf are enumerated starting in the top left corner and
+	 * reading each line at a time from left to right */
+	for (y = 0; y != last_y; y++, buf += _videoMode.screenWidth * (8 - 1))
+		for (x = 0; x != last_x; x++, buf += 8) {
+			// Adler32 checksum algorithm (from RFC1950, used by gzip and zlib).
+			// This computes the Adler32 checksum of a 8x8 pixel block. Note
+			// that we can do the modulo operation (which is the slowest part)
+			// of the algorithm) at the end, instead of doing each iteration,
+			// since we only have 64 iterations in total - and thus s1 and
+			// s2 can't overflow anyway.
+			uint32 s1 = 1;
+			uint32 s2 = 0;
+			const byte *ptr = buf;
+			for (int subY = 0; subY < 8; subY++) {
+				for (int subX = 0; subX < 8; subX++) {
+					s1 += ptr[subX];
+					s2 += s1;
+				}
+				ptr += _videoMode.screenWidth;
+			}
+
+			s1 %= BASE;
+			s2 %= BASE;
+
+			/* output the checksum for this block */
+			*sums++ =  (s2 << 16) + s1;
+	}
+}
+
+void OSystem_SDL_SamsungTV::addDirtyRgnAuto(const byte *buf) {
+	assert(buf);
+	assert(IS_ALIGNED(buf, 4));
+
+	/* generate a table of the checksums */
+	makeChecksums(buf);
+
+	if (!_cksumValid) {
+		_forceFull = true;
+		_cksumValid = true;
+	}
+
+	/* go through the checksum list, compare it with the previous checksums,
+		 and add all dirty rectangles to a list. try to combine small rectangles
+		 into bigger ones in a simple way */
+	if (!_forceFull) {
+		int x, y, w;
+		uint32 *ck = _dirtyChecksums;
+
+		for (y = 0; y != _videoMode.screenHeight / 8; y++) {
+			for (x = 0; x != _videoMode.screenWidth / 8; x++, ck++) {
+				if (ck[0] != ck[_cksumNum]) {
+					/* found a dirty 8x8 block, now go as far to the right as possible,
+						 and at the same time, unmark the dirty status by setting old to new. */
+					w=0;
+					do {
+						ck[w + _cksumNum] = ck[w];
+						w++;
+					} while (x + w != _videoMode.screenWidth / 8 && ck[w] != ck[w + _cksumNum]);
+
+					addDirtyRect(x * 8, y * 8, w * 8, 8);
+
+					if (_forceFull)
+						goto get_out;
+				}
+			}
+		}
+	} else {
+		get_out:;
+		/* Copy old checksums to new */
+		memcpy(_dirtyChecksums + _cksumNum, _dirtyChecksums, _cksumNum * sizeof(uint32));
+	}
+}
+
+int16 OSystem_SDL_SamsungTV::getHeight() {
+	return _videoMode.screenHeight;
+}
+
+int16 OSystem_SDL_SamsungTV::getWidth() {
+	return _videoMode.screenWidth;
+}
+
+void OSystem_SDL_SamsungTV::setPalette(const byte *colors, uint start, uint num) {
+	assert(colors);
+
+	if (_screenFormat.bytesPerPixel > 1)
+		return; //not using a paletted pixel format
+
+	// Setting the palette before _screen is created is allowed - for now -
+	// since we don't actually set the palette until the screen is updated.
+	// But it could indicate a programming error, so let's warn about it.
+
+	if (!_screen)
+		warning("OSystem_SDL::setPalette: _screen == NULL");
+
+	const byte *b = colors;
+	uint i;
+	SDL_Color *base = _currentPalette + start;
+	for (i = 0; i < num; i++) {
+		base[i].r = b[0];
+		base[i].g = b[1];
+		base[i].b = b[2];
+		b += 4;
+	}
+
+	if (start < _paletteDirtyStart)
+		_paletteDirtyStart = start;
+
+	if (start + num > _paletteDirtyEnd)
+		_paletteDirtyEnd = start + num;
+
+	// Some games blink cursors with palette
+	if (_cursorPaletteDisabled)
+		blitCursor();
+}
+
+void OSystem_SDL_SamsungTV::grabPalette(byte *colors, uint start, uint num) {
+	assert(colors);
+	const SDL_Color *base = _currentPalette + start;
+
+	for (uint i = 0; i < num; ++i) {
+		colors[i * 4] = base[i].r;
+		colors[i * 4 + 1] = base[i].g;
+		colors[i * 4 + 2] = base[i].b;
+		colors[i * 4 + 3] = 0xFF;
+	}
+}
+
+void OSystem_SDL_SamsungTV::setCursorPalette(const byte *colors, uint start, uint num) {
+	assert(colors);
+	const byte *b = colors;
+	uint i;
+	SDL_Color *base = _cursorPalette + start;
+	for (i = 0; i < num; i++) {
+		base[i].r = b[0];
+		base[i].g = b[1];
+		base[i].b = b[2];
+		b += 4;
+	}
+
+	_cursorPaletteDisabled = false;
+	blitCursor();
+}
+
+
+void OSystem_SDL_SamsungTV::setShakePos(int shake_pos) {
+	assert (_transactionMode == kTransactionNone);
+
+	_newShakePos = shake_pos;
+}
+
+
+#pragma mark -
+#pragma mark --- Overlays ---
+#pragma mark -
+
+void OSystem_SDL_SamsungTV::showOverlay() {
+	assert (_transactionMode == kTransactionNone);
+
+	int x, y;
+
+	if (_overlayVisible)
+		return;
+
+	_overlayVisible = true;
+
+	// Since resolution could change, put mouse to adjusted position
+	// Fixes bug #1349059
+	x = _mouseCurState.x * _videoMode.scaleFactor;
+	if (_videoMode.aspectRatioCorrection)
+		y = real2Aspect(_mouseCurState.y) * _videoMode.scaleFactor;
+	else
+		y = _mouseCurState.y * _videoMode.scaleFactor;
+
+	warpMouse(x, y);
+
+	clearOverlay();
+}
+
+void OSystem_SDL_SamsungTV::hideOverlay() {
+	assert (_transactionMode == kTransactionNone);
+
+	if (!_overlayVisible)
+		return;
+
+	int x, y;
+
+	_overlayVisible = false;
+
+	// Since resolution could change, put mouse to adjusted position
+	// Fixes bug #1349059
+	x = _mouseCurState.x / _videoMode.scaleFactor;
+	y = _mouseCurState.y / _videoMode.scaleFactor;
+	if (_videoMode.aspectRatioCorrection)
+		y = aspect2Real(y);
+
+	warpMouse(x, y);
+
+	clearOverlay();
+
+	_forceFull = true;
+}
+
+void OSystem_SDL_SamsungTV::clearOverlay() {
+	//assert (_transactionMode == kTransactionNone);
+	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
+
+	if (!_overlayVisible)
+		return;
+
+	// Clear the overlay by making the game screen "look through" everywhere.
+	SDL_Rect src, dst;
+	src.x = src.y = 0;
+	dst.x = dst.y = 1;
+	src.w = dst.w = _videoMode.screenWidth;
+	src.h = dst.h = _videoMode.screenHeight;
+	if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
+		error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+	SDL_LockSurface(_tmpscreen);
+	SDL_LockSurface(_overlayscreen);
+	
+	_scalerProc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, _tmpscreen->pitch,
+	(byte *)_overlayscreen->pixels, _overlayscreen->pitch, _videoMode.screenWidth, _videoMode.screenHeight);
+
+#ifndef DISABLE_SCALERS
+	if (_videoMode.aspectRatioCorrection)
+		stretch200To240((uint8 *)_overlayscreen->pixels, _overlayscreen->pitch,
+						_videoMode.overlayWidth, _videoMode.screenHeight * _videoMode.scaleFactor, 0, 0, 0);
+#endif
+	SDL_UnlockSurface(_tmpscreen);
+	SDL_UnlockSurface(_overlayscreen);
+
+	_forceFull = true;
+}
+
+void OSystem_SDL_SamsungTV::grabOverlay(OverlayColor *buf, int pitch) {
+	assert (_transactionMode == kTransactionNone);
+
+	if (_overlayscreen == NULL)
+		return;
+
+	if (SDL_LockSurface(_overlayscreen) == -1)
+		error("SDL_LockSurface failed: %s", SDL_GetError());
+
+	byte *src = (byte *)_overlayscreen->pixels;
+	int h = _videoMode.overlayHeight;
+	do {
+		memcpy(buf, src, _videoMode.overlayWidth * 2);
+		src += _overlayscreen->pitch;
+		buf += pitch;
+	} while (--h);
+
+	SDL_UnlockSurface(_overlayscreen);
+}
+
+void OSystem_SDL_SamsungTV::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
+	assert (_transactionMode == kTransactionNone);
+
+	if (_overlayscreen == NULL)
+		return;
+
+	// Clip the coordinates
+	if (x < 0) {
+		w += x;
+		buf -= x;
+		x = 0;
+	}
+
+	if (y < 0) {
+		h += y; buf -= y * pitch;
+		y = 0;
+	}
+
+	if (w > _videoMode.overlayWidth - x) {
+		w = _videoMode.overlayWidth - x;
+	}
+
+	if (h > _videoMode.overlayHeight - y) {
+		h = _videoMode.overlayHeight - y;
+	}
+
+	if (w <= 0 || h <= 0)
+		return;
+
+	// Mark the modified region as dirty
+	_cksumValid = false;
+	addDirtyRect(x, y, w, h);
+
+	if (SDL_LockSurface(_overlayscreen) == -1)
+		error("SDL_LockSurface failed: %s", SDL_GetError());
+
+	byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
+	do {
+		memcpy(dst, buf, w * 2);
+		dst += _overlayscreen->pitch;
+		buf += pitch;
+	} while (--h);
+
+	SDL_UnlockSurface(_overlayscreen);
+}
+
+
+#pragma mark -
+#pragma mark --- Mouse ---
+#pragma mark -
+
+bool OSystem_SDL_SamsungTV::showMouse(bool visible) {
+	if (_mouseVisible == visible)
+		return visible;
+
+	bool last = _mouseVisible;
+	_mouseVisible = visible;
+	_mouseNeedsRedraw = true;
+
+	return last;
+}
+
+void OSystem_SDL_SamsungTV::setMousePos(int x, int y) {
+	if (x != _mouseCurState.x || y != _mouseCurState.y) {
+		_mouseNeedsRedraw = true;
+		_mouseCurState.x = x;
+		_mouseCurState.y = y;
+	}
+}
+
+void OSystem_SDL_SamsungTV::warpMouse(int x, int y) {
+	int y1 = y;
+
+	if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+		y1 = real2Aspect(y);
+
+	if (_mouseCurState.x != x || _mouseCurState.y != y)
+		setMousePos(x, y);
+}
+
+void OSystem_SDL_SamsungTV::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format) {
+	if (!format)
+		_cursorFormat = Graphics::PixelFormat::createFormatCLUT8();
+	else if (format->bytesPerPixel <= _screenFormat.bytesPerPixel)
+		_cursorFormat = *format;
+	keycolor &= (1 << (_cursorFormat.bytesPerPixel << 3)) - 1;
+
+	if (w == 0 || h == 0)
+		return;
+
+	_mouseCurState.hotX = hotspot_x;
+	_mouseCurState.hotY = hotspot_y;
+
+	_mouseKeyColor = keycolor;
+
+	_cursorTargetScale = cursorTargetScale;
+
+	if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
+		_mouseCurState.w = w;
+		_mouseCurState.h = h;
+
+		if (_mouseOrigSurface)
+			SDL_FreeSurface(_mouseOrigSurface);
+
+		// Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
+		_mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_mouseCurState.w + 2,
+						_mouseCurState.h + 2,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+
+		if (_mouseOrigSurface == NULL)
+			error("allocating _mouseOrigSurface failed");
+		SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+	}
+
+	free(_mouseData);
+	_mouseData = (byte *)malloc(w * h * _cursorFormat.bytesPerPixel);
+	memcpy(_mouseData, buf, w * h * _cursorFormat.bytesPerPixel);
+
+	blitCursor();
+}
+
+void OSystem_SDL_SamsungTV::blitCursor() {
+	byte *dstPtr;
+	const byte *srcPtr = _mouseData;
+	uint32 color;
+	int w, h, i, j;
+
+	if (!_mouseOrigSurface || !_mouseData)
+		return;
+
+	_mouseNeedsRedraw = true;
+
+	w = _mouseCurState.w;
+	h = _mouseCurState.h;
+
+	SDL_LockSurface(_mouseOrigSurface);
+
+	// Make whole surface transparent
+	for (i = 0; i < h + 2; i++) {
+		dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i;
+		for (j = 0; j < w + 2; j++) {
+			*(uint16 *)dstPtr = kMouseColorKey;
+			dstPtr += 2;
+		}
+	}
+
+	// Draw from [1,1] since AdvMame2x adds artefact at 0,0
+	dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2;
+
+	SDL_Color *palette;
+
+	if (_cursorPaletteDisabled)
+		palette = _currentPalette;
+	else
+		palette = _cursorPalette;
+
+	for (i = 0; i < h; i++) {
+		for (j = 0; j < w; j++) {
+			if (_cursorFormat.bytesPerPixel > 1) {
+				if (_cursorFormat.bytesPerPixel == 2)
+					color = *(uint16 *)srcPtr;
+				else
+					color = *(uint32 *)srcPtr;
+				if (color != _mouseKeyColor) {	// transparent, don't draw
+					uint8 r, g, b;
+					_cursorFormat.colorToRGB(color, r, g, b);
+					*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
+						r, g, b);
+				}
+				dstPtr += 2;
+				srcPtr += _cursorFormat.bytesPerPixel;
+			} else {
+				color = *srcPtr;
+				if (color != _mouseKeyColor) {	// transparent, don't draw
+					*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format,
+						palette[color].r, palette[color].g, palette[color].b);
+				}
+				dstPtr += 2;
+				srcPtr++;
+			}
+		}
+		dstPtr += _mouseOrigSurface->pitch - w * 2;
+	}
+
+	int rW, rH;
+
+	if (_cursorTargetScale >= _videoMode.scaleFactor) {
+		// The cursor target scale is greater or equal to the scale at
+		// which the rest of the screen is drawn. We do not downscale
+		// the cursor image, we draw it at its original size. It will
+		// appear too large on screen.
+
+		rW = w;
+		rH = h;
+		_mouseCurState.rHotX = _mouseCurState.hotX;
+		_mouseCurState.rHotY = _mouseCurState.hotY;
+
+		// The virtual dimensions may be larger than the original.
+
+		_mouseCurState.vW = w * _cursorTargetScale / _videoMode.scaleFactor;
+		_mouseCurState.vH = h * _cursorTargetScale / _videoMode.scaleFactor;
+		_mouseCurState.vHotX = _mouseCurState.hotX * _cursorTargetScale /
+			_videoMode.scaleFactor;
+		_mouseCurState.vHotY = _mouseCurState.hotY * _cursorTargetScale /
+			_videoMode.scaleFactor;
+	} else {
+		// The cursor target scale is smaller than the scale at which
+		// the rest of the screen is drawn. We scale up the cursor
+		// image to make it appear correct.
+
+		rW = w * _videoMode.scaleFactor / _cursorTargetScale;
+		rH = h * _videoMode.scaleFactor / _cursorTargetScale;
+		_mouseCurState.rHotX = _mouseCurState.hotX * _videoMode.scaleFactor /
+			_cursorTargetScale;
+		_mouseCurState.rHotY = _mouseCurState.hotY * _videoMode.scaleFactor /
+			_cursorTargetScale;
+
+		// The virtual dimensions will be the same as the original.
+
+		_mouseCurState.vW = w;
+		_mouseCurState.vH = h;
+		_mouseCurState.vHotX = _mouseCurState.hotX;
+		_mouseCurState.vHotY = _mouseCurState.hotY;
+	}
+
+#ifndef DISABLE_SCALERS
+	int rH1 = rH; // store original to pass to aspect-correction function later
+#endif
+
+	if (_videoMode.aspectRatioCorrection && _cursorTargetScale == 1) {
+		rH = real2Aspect(rH - 1) + 1;
+		_mouseCurState.rHotY = real2Aspect(_mouseCurState.rHotY);
+	}
+
+	if (_mouseCurState.rW != rW || _mouseCurState.rH != rH) {
+		_mouseCurState.rW = rW;
+		_mouseCurState.rH = rH;
+
+		if (_mouseSurface)
+			SDL_FreeSurface(_mouseSurface);
+
+		_mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_mouseCurState.rW,
+						_mouseCurState.rH,
+						16,
+						0x0000f800,
+						0x000007e0,
+						0x0000001f,
+						0x00000000);
+
+		if (_mouseSurface == NULL)
+			error("allocating _mouseSurface failed");
+
+		SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+	}
+
+	SDL_LockSurface(_mouseSurface);
+
+	ScalerProc *scalerProc;
+
+	// If possible, use the same scaler for the cursor as for the rest of
+	// the game. This only works well with the non-blurring scalers so we
+	// actually only use the 1x, 1.5x, 2x and AdvMame scalers.
+
+	if (_cursorTargetScale == 1 && (_videoMode.mode == GFX_DOUBLESIZE || _videoMode.mode == GFX_TRIPLESIZE))
+		scalerProc = _scalerProc;
+	else
+		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);
+
+#ifndef DISABLE_SCALERS
+	if (_videoMode.aspectRatioCorrection && _cursorTargetScale == 1)
+		cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, rW, rH1, 0, 0, 0);
+#endif
+
+	SDL_UnlockSurface(_mouseSurface);
+	SDL_UnlockSurface(_mouseOrigSurface);
+}
+
+#ifndef DISABLE_SCALERS
+// Basically it is kVeryFastAndUglyAspectMode of stretch200To240 from
+// common/scale/aspect.cpp
+static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY) {
+	int maxDstY = real2Aspect(origSrcY + height - 1);
+	int y;
+	const uint8 *startSrcPtr = buf + srcX * 2 + (srcY - origSrcY) * pitch;
+	uint8 *dstPtr = buf + srcX * 2 + maxDstY * pitch;
+
+	for (y = maxDstY; y >= srcY; y--) {
+		const uint8 *srcPtr = startSrcPtr + aspect2Real(y) * pitch;
+
+		if (srcPtr == dstPtr)
+			break;
+		memcpy(dstPtr, srcPtr, width * 2);
+		dstPtr -= pitch;
+	}
+
+	return 1 + maxDstY - srcY;
+}
+#endif
+
+void OSystem_SDL_SamsungTV::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_SDL_SamsungTV::undrawMouse() {
+	const int x = _mouseBackup.x;
+	const int y = _mouseBackup.y;
+
+	// When we switch bigger overlay off mouse jumps. Argh!
+	// This is intended to prevent undrawing offscreen mouse
+	if (!_overlayVisible && (x >= _videoMode.screenWidth || y >= _videoMode.screenHeight))
+		return;
+
+	if (_mouseBackup.w != 0 && _mouseBackup.h != 0)
+		addDirtyRect(x, y, _mouseBackup.w, _mouseBackup.h);
+}
+
+void OSystem_SDL_SamsungTV::drawMouse() {
+	if (!_mouseVisible || !_mouseSurface) {
+		_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
+		return;
+	}
+
+	SDL_Rect dst;
+	int scale;
+	int width, height;
+	int hotX, hotY;
+
+	dst.x = _mouseCurState.x;
+	dst.y = _mouseCurState.y;
+
+	if (!_overlayVisible) {
+		scale = _videoMode.scaleFactor;
+		width = _videoMode.screenWidth;
+		height = _videoMode.screenHeight;
+		dst.w = _mouseCurState.vW;
+		dst.h = _mouseCurState.vH;
+		hotX = _mouseCurState.vHotX;
+		hotY = _mouseCurState.vHotY;
+	} else {
+		scale = 1;
+		width = _videoMode.overlayWidth;
+		height = _videoMode.overlayHeight;
+		dst.w = _mouseCurState.rW;
+		dst.h = _mouseCurState.rH;
+		hotX = _mouseCurState.rHotX;
+		hotY = _mouseCurState.rHotY;
+	}
+
+	// The mouse is undrawn using virtual coordinates, i.e. they may be
+	// scaled and aspect-ratio corrected.
+
+	_mouseBackup.x = dst.x - hotX;
+	_mouseBackup.y = dst.y - hotY;
+	_mouseBackup.w = dst.w;
+	_mouseBackup.h = dst.h;
+
+	// We draw the pre-scaled cursor image, so now we need to adjust for
+	// scaling, shake position and aspect ratio correction manually.
+
+	if (!_overlayVisible) {
+		dst.y += _currentShakePos;
+	}
+
+	if (_videoMode.aspectRatioCorrection && !_overlayVisible)
+		dst.y = real2Aspect(dst.y);
+
+	dst.x = scale * dst.x - _mouseCurState.rHotX;
+	dst.y = scale * dst.y - _mouseCurState.rHotY;
+	dst.w = _mouseCurState.rW;
+	dst.h = _mouseCurState.rH;
+
+	// Note that SDL_BlitSurface() and addDirtyRect() will both perform any
+	// clipping necessary
+
+	if (SDL_BlitSurface(_mouseSurface, NULL, _prehwscreen, &dst) != 0)
+		error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+	// The screen will be updated using real surface coordinates, i.e.
+	// they will not be scaled or aspect-ratio corrected.
+
+	addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
+}
+
+#pragma mark -
+#pragma mark --- On Screen Display ---
+#pragma mark -
+
+#ifdef USE_OSD
+void OSystem_SDL_SamsungTV::displayMessageOnOSD(const char *msg) {
+	assert (_transactionMode == kTransactionNone);
+	assert(msg);
+
+	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
+
+	uint i;
+
+	// Lock the OSD surface for drawing
+	if (SDL_LockSurface(_osdSurface))
+		error("displayMessageOnOSD: SDL_LockSurface failed: %s", SDL_GetError());
+
+	Graphics::Surface dst;
+	dst.pixels = _osdSurface->pixels;
+	dst.w = _osdSurface->w;
+	dst.h = _osdSurface->h;
+	dst.pitch = _osdSurface->pitch;
+	dst.bytesPerPixel = _osdSurface->format->BytesPerPixel;
+
+	// The font we are going to use:
+	const Graphics::Font *font = FontMan.getFontByUsage(Graphics::FontManager::kOSDFont);
+
+	// Clear everything with the "transparent" color, i.e. the colorkey
+	SDL_FillRect(_osdSurface, 0, kOSDColorKey);
+
+	// Split the message into separate lines.
+	Common::StringList lines;
+	const char *ptr;
+	for (ptr = msg; *ptr; ++ptr) {
+		if (*ptr == '\n') {
+			lines.push_back(Common::String(msg, ptr - msg));
+			msg = ptr + 1;
+		}
+	}
+	lines.push_back(Common::String(msg, ptr - msg));
+
+	// Determine a rect which would contain the message string (clipped to the
+	// screen dimensions).
+	const int vOffset = 6;
+	const int lineSpacing = 1;
+	const int lineHeight = font->getFontHeight() + 2 * lineSpacing;
+	int width = 0;
+	int height = lineHeight * lines.size() + 2 * vOffset;
+	for (i = 0; i < lines.size(); i++) {
+		width = MAX(width, font->getStringWidth(lines[i]) + 14);
+	}
+
+	// Clip the rect
+	if (width > dst.w)
+		width = dst.w;
+	if (height > dst.h)
+		height = dst.h;
+
+	// Draw a dark gray rect
+	// TODO: Rounded corners ? Border?
+	SDL_Rect osdRect;
+	osdRect.x = (dst.w - width) / 2;
+	osdRect.y = (dst.h - height) / 2;
+	osdRect.w = width;
+	osdRect.h = height;
+	SDL_FillRect(_osdSurface, &osdRect, SDL_MapRGB(_osdSurface->format, 64, 64, 64));
+
+	// Render the message, centered, and in white
+	for (i = 0; i < lines.size(); i++) {
+		font->drawString(&dst, lines[i],
+							osdRect.x, osdRect.y + i * lineHeight + vOffset + lineSpacing, osdRect.w,
+							SDL_MapRGB(_osdSurface->format, 255, 255, 255),
+							Graphics::kTextAlignCenter);
+	}
+
+	// Finished drawing, so unlock the OSD surface again
+	SDL_UnlockSurface(_osdSurface);
+
+	// Init the OSD display parameters, and the fade out
+	_osdAlpha = SDL_ALPHA_TRANSPARENT +  kOSDInitialAlpha * (SDL_ALPHA_OPAQUE - SDL_ALPHA_TRANSPARENT) / 100;
+	_osdFadeStartTime = SDL_GetTicks() + kOSDFadeOutDelay;
+	SDL_SetAlpha(_osdSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, _osdAlpha);
+
+	// Ensure a full redraw takes place next time the screen is updated
+	_forceFull = true;
+}
+#endif
+
+
+#pragma mark -
+#pragma mark --- Misc ---
+#pragma mark -
+
+void OSystem_SDL_SamsungTV::handleScalerHotkeys(const SDL_KeyboardEvent &key) {
+	// Ctrl-Alt-a toggles aspect ratio correction
+	if (key.keysym.sym == 'a') {
+		beginGFXTransaction();
+			setFeatureState(kFeatureAspectRatioCorrection, !_videoMode.aspectRatioCorrection);
+		endGFXTransaction();
+#ifdef USE_OSD
+		char buffer[128];
+		if (_videoMode.aspectRatioCorrection)
+			sprintf(buffer, "Enabled aspect ratio correction\n%d x %d -> %d x %d",
+				_videoMode.screenWidth, _videoMode.screenHeight,
+				_hwscreen->w, _hwscreen->h
+				);
+		else
+			sprintf(buffer, "Disabled aspect ratio correction\n%d x %d -> %d x %d",
+				_videoMode.screenWidth, _videoMode.screenHeight,
+				_hwscreen->w, _hwscreen->h
+				);
+		displayMessageOnOSD(buffer);
+#endif
+		internUpdateScreen();
+		return;
+	}
+
+	int newMode = -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 ||
+		key.keysym.sym == SDLK_KP_PLUS || key.keysym.sym == SDLK_KP_MINUS) {
+		factor += (key.keysym.sym == SDLK_MINUS || key.keysym.sym == SDLK_KP_MINUS) ? -1 : +1;
+		if (0 <= factor && factor <= 3) {
+			newMode = s_gfxModeSwitchTable[_scalerType][factor];
+		}
+	}
+
+	const bool isNormalNumber = (SDLK_1 <= key.keysym.sym && key.keysym.sym <= SDLK_9);
+	const bool isKeypadNumber = (SDLK_KP1 <= key.keysym.sym && key.keysym.sym <= SDLK_KP9);
+	if (isNormalNumber || isKeypadNumber) {
+		_scalerType = key.keysym.sym - (isNormalNumber ? SDLK_1 : SDLK_KP1);
+		if (_scalerType >= ARRAYSIZE(s_gfxModeSwitchTable))
+			return;
+
+		while (s_gfxModeSwitchTable[_scalerType][factor] < 0) {
+			assert(factor > 0);
+			factor--;
+		}
+		newMode = s_gfxModeSwitchTable[_scalerType][factor];
+	}
+
+	if (newMode >= 0) {
+		beginGFXTransaction();
+			setGraphicsMode(newMode);
+		endGFXTransaction();
+#ifdef USE_OSD
+		if (_osdSurface) {
+			const char *newScalerName = 0;
+			const GraphicsMode *g = getSupportedGraphicsModes();
+			while (g->name) {
+				if (g->id == _videoMode.mode) {
+					newScalerName = g->description;
+					break;
+				}
+				g++;
+			}
+			if (newScalerName) {
+				char buffer[128];
+				sprintf(buffer, "Active graphics filter: %s\n%d x %d -> %d x %d",
+					newScalerName,
+					_videoMode.screenWidth, _videoMode.screenHeight,
+					_hwscreen->w, _hwscreen->h
+					);
+				displayMessageOnOSD(buffer);
+			}
+		}
+#endif
+		internUpdateScreen();
+	}
+
+}
+
+#endif


Property changes on: scummvm/trunk/backends/platform/samsungtv/graphics.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/hardwarekeys.cpp
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/hardwarekeys.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/hardwarekeys.cpp	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,237 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/hardwarekeys.cpp $
+ * $Id: hardwarekeys.cpp 40516 2009-05-12 23:31:02Z fingolfin $
+ *
+ */
+
+#include "backends/platform/samsungtv/sdl.h"
+#include "backends/keymapper/keymapper.h"
+#include "common/keyboard.h"
+
+#if defined(SAMSUNGTV)
+
+#ifdef ENABLE_KEYMAPPER
+
+using namespace Common;
+
+struct Key {
+	const char *hwId;
+	KeyCode keycode;
+	uint16 ascii;
+	const char *desc;
+	KeyType preferredAction;
+	bool shiftable;
+};
+
+static const Key keys[] = {
+	{"BACKSPACE", KEYCODE_BACKSPACE, ASCII_BACKSPACE, "Backspace", kActionKeyType, false},
+	{"TAB", KEYCODE_TAB, ASCII_TAB, "Tab", kActionKeyType, false},
+	{"CLEAR", KEYCODE_CLEAR, 0, "Clear", kActionKeyType, false},
+	{"RETURN", KEYCODE_RETURN, ASCII_RETURN, "Return", kActionKeyType, false},
+	{"PAUSE", KEYCODE_PAUSE, 0, "Pause", kActionKeyType, false},
+	{"ESCAPE", KEYCODE_ESCAPE, ASCII_ESCAPE, "Esc", kStartKeyType, false},
+	{"SPACE", KEYCODE_SPACE, ASCII_SPACE, "Space", kActionKeyType, false},
+	{"EXCLAIM", KEYCODE_EXCLAIM, '!', "!", kActionKeyType, false},
+	{"QUOTEDBL", KEYCODE_QUOTEDBL, '"', "\"", kActionKeyType, false},
+	{"HASH", KEYCODE_HASH, '#', "#", kActionKeyType, false},
+	{"DOLLAR", KEYCODE_DOLLAR, '$', "$", kActionKeyType, false},
+	{"AMPERSAND", KEYCODE_AMPERSAND, '&', "&", kActionKeyType, false},
+	{"QUOTE", KEYCODE_QUOTE, '\'', "'", kActionKeyType, false},
+	{"LEFTPAREN", KEYCODE_LEFTPAREN, '(', "(", kActionKeyType, false},
+	{"RIGHTPAREN", KEYCODE_RIGHTPAREN, ')', ")", kActionKeyType, false},
+	{"ASTERISK", KEYCODE_ASTERISK, '*', "*", kActionKeyType, false},
+	{"PLUS", KEYCODE_PLUS, '+', "+", kActionKeyType, false},
+	{"COMMA", KEYCODE_COMMA, ',', ",", kActionKeyType, false},
+	{"MINUS", KEYCODE_MINUS, '-', "-", kActionKeyType, false},
+	{"PERIOD", KEYCODE_PERIOD, '.', ".", kActionKeyType, false},
+	{"SLASH", KEYCODE_SLASH, '/', "/", kActionKeyType, false},
+	{"0", KEYCODE_0, '0', "0", kActionKeyType, false},
+	{"1", KEYCODE_1, '1', "1", kActionKeyType, false},
+	{"2", KEYCODE_2, '2', "2", kActionKeyType, false},
+	{"3", KEYCODE_3, '3', "3", kActionKeyType, false},
+	{"4", KEYCODE_4, '4', "4", kActionKeyType, false},
+	{"5", KEYCODE_5, '5', "5", kActionKeyType, false},
+	{"6", KEYCODE_6, '6', "6", kActionKeyType, false},
+	{"7", KEYCODE_7, '7', "7", kActionKeyType, false},
+	{"8", KEYCODE_8, '8', "8", kActionKeyType, false},
+	{"9", KEYCODE_9, '9', "9", kActionKeyType, false},
+	{"COLON", KEYCODE_COLON, ':', ":", kActionKeyType, false},
+	{"SEMICOLON", KEYCODE_SEMICOLON, ';', ";", kActionKeyType, false},
+	{"LESS", KEYCODE_LESS, '<', "<", kActionKeyType, false},
+	{"EQUALS", KEYCODE_EQUALS, '=', "=", kActionKeyType, false},
+	{"GREATER", KEYCODE_GREATER, '>', ">", kActionKeyType, false},
+	{"QUESTION", KEYCODE_QUESTION, '?', "?", kActionKeyType, false},
+	{"AT", KEYCODE_AT, '@', "@", kActionKeyType, false},
+
+	{"LEFTBRACKET", KEYCODE_LEFTBRACKET, '[', "[", kActionKeyType, false},
+	{"BACKSLASH", KEYCODE_BACKSLASH, '\\', "\\", kActionKeyType, false},
+	{"RIGHTBRACKET", KEYCODE_RIGHTBRACKET, ']', "]", kActionKeyType, false},
+	{"CARET", KEYCODE_CARET, '^', "^", kActionKeyType, false},
+	{"UNDERSCORE", KEYCODE_UNDERSCORE, '_', "_", kActionKeyType, false},
+	{"BACKQUOTE", KEYCODE_BACKQUOTE, '`', "`", kActionKeyType, false},
+	{"a", KEYCODE_a, 'a', "a", kActionKeyType, true},
+	{"b", KEYCODE_b, 'b', "b", kActionKeyType, true},
+	{"c", KEYCODE_c, 'c', "c", kActionKeyType, true},
+	{"d", KEYCODE_d, 'd', "d", kActionKeyType, true},
+	{"e", KEYCODE_e, 'e', "e", kActionKeyType, true},
+	{"f", KEYCODE_f, 'f', "f", kActionKeyType, true},
+	{"g", KEYCODE_g, 'g', "g", kActionKeyType, true},
+	{"h", KEYCODE_h, 'h', "h", kActionKeyType, true},
+	{"i", KEYCODE_i, 'i', "i", kActionKeyType, true},
+	{"j", KEYCODE_j, 'j', "j", kActionKeyType, true},
+	{"k", KEYCODE_k, 'k', "k", kActionKeyType, true},
+	{"l", KEYCODE_l, 'l', "l", kActionKeyType, true},
+	{"m", KEYCODE_m, 'm', "m", kActionKeyType, true},
+	{"n", KEYCODE_n, 'n', "n", kActionKeyType, true},
+	{"o", KEYCODE_o, 'o', "o", kActionKeyType, true},
+	{"p", KEYCODE_p, 'p', "p", kActionKeyType, true},
+	{"q", KEYCODE_q, 'q', "q", kActionKeyType, true},
+	{"r", KEYCODE_r, 'r', "r", kActionKeyType, true},
+	{"s", KEYCODE_s, 's', "s", kActionKeyType, true},
+	{"t", KEYCODE_t, 't', "t", kActionKeyType, true},
+	{"u", KEYCODE_u, 'u', "u", kActionKeyType, true},
+	{"v", KEYCODE_v, 'v', "v", kActionKeyType, true},
+	{"w", KEYCODE_w, 'w', "w", kActionKeyType, true},
+	{"x", KEYCODE_x, 'x', "x", kActionKeyType, true},
+	{"y", KEYCODE_y, 'y', "y", kActionKeyType, true},
+	{"z", KEYCODE_z, 'z', "z", kActionKeyType, true},
+	{"DELETE", KEYCODE_DELETE, 0, "Del", kActionKeyType, false},
+
+	// Numeric keypad
+	{"KP0", KEYCODE_KP0, 0, "KP0", kActionKeyType, false},
+	{"KP1", KEYCODE_KP1, 0, "KP1", kActionKeyType, false},
+	{"KP2", KEYCODE_KP2, 0, "KP2", kActionKeyType, false},
+	{"KP3", KEYCODE_KP3, 0, "KP3", kActionKeyType, false},
+	{"KP4", KEYCODE_KP4, 0, "KP4", kActionKeyType, false},
+	{"KP5", KEYCODE_KP5, 0, "KP5", kActionKeyType, false},
+	{"KP6", KEYCODE_KP6, 0, "KP6", kActionKeyType, false},
+	{"KP7", KEYCODE_KP7, 0, "KP7", kActionKeyType, false},
+	{"KP8", KEYCODE_KP8, 0, "KP8", kActionKeyType, false},
+	{"KP9", KEYCODE_KP9, 0, "KP9", kActionKeyType, false},
+	{"KP_PERIOD", KEYCODE_KP_PERIOD, 0, "KP.", kActionKeyType, false},
+	{"KP_DIVIDE", KEYCODE_KP_DIVIDE, 0, "KP/", kActionKeyType, false},
+	{"KP_MULTIPLY", KEYCODE_KP_MULTIPLY, 0, "KP*", kActionKeyType, false},
+	{"KP_MINUS", KEYCODE_KP_MINUS, 0, "KP-", kActionKeyType, false},
+	{"KP_PLUS", KEYCODE_KP_PLUS, 0, "KP+", kActionKeyType, false},
+	{"KP_ENTER", KEYCODE_KP_ENTER, 0, "KP Enter", kActionKeyType, false},
+	{"KP_EQUALS", KEYCODE_KP_EQUALS, 0, "KP=", kActionKeyType, false},
+
+	// Arrows + Home/End pad
+	{"UP", KEYCODE_UP, 0, "Up", kDirUpKeyType, false},
+	{"DOWN", KEYCODE_DOWN, 0, "Down", kDirDownKeyType, false},
+	{"RIGHT", KEYCODE_RIGHT, 0, "Right", kDirRightKeyType, false},
+	{"LEFT", KEYCODE_LEFT, 0, "Left", kDirLeftKeyType, false},
+	{"INSERT", KEYCODE_INSERT, 0, "Insert", kActionKeyType, false},
+	{"HOME", KEYCODE_HOME, 0, "Home", kActionKeyType, false},
+	{"END", KEYCODE_END, 0, "End", kActionKeyType, false},
+	{"PAGEUP", KEYCODE_PAGEUP, 0, "PgUp", kActionKeyType, false},
+	{"PAGEDOWN", KEYCODE_PAGEDOWN, 0, "PgDn", kActionKeyType, false},
+
+	// Function keys
+	{"F1", KEYCODE_F1, ASCII_F1, "F1", kActionKeyType, false},
+	{"F2", KEYCODE_F2, ASCII_F2, "F2", kActionKeyType, false},
+	{"F3", KEYCODE_F3, ASCII_F3, "F3", kActionKeyType, false},
+	{"F4", KEYCODE_F4, ASCII_F4, "F4", kActionKeyType, false},
+	{"F5", KEYCODE_F5, ASCII_F5, "F5", kActionKeyType, false},
+	{"F6", KEYCODE_F6, ASCII_F6, "F6", kActionKeyType, false},
+	{"F7", KEYCODE_F7, ASCII_F7, "F7", kActionKeyType, false},
+	{"F8", KEYCODE_F8, ASCII_F8, "F8", kActionKeyType, false},
+	{"F9", KEYCODE_F9, ASCII_F9, "F9", kActionKeyType, false},
+	{"F10", KEYCODE_F10, ASCII_F10, "F10", kActionKeyType, false},
+	{"F11", KEYCODE_F11, ASCII_F11, "F11", kActionKeyType, false},
+	{"F12", KEYCODE_F12, ASCII_F12, "F12", kActionKeyType, false},
+	{"F13", KEYCODE_F13, 0, "F13", kActionKeyType, false},
+	{"F14", KEYCODE_F14, 0, "F14", kActionKeyType, false},
+	{"F15", KEYCODE_F15, 0, "F15", kActionKeyType, false},
+
+	// Miscellaneous function keys
+	{"HELP", KEYCODE_HELP, 0, "Help", kActionKeyType, false},
+	{"PRINT", KEYCODE_PRINT, 0, "Print", kActionKeyType, false},
+	{"SYSREQ", KEYCODE_SYSREQ, 0, "SysRq", kActionKeyType, false},
+	{"BREAK", KEYCODE_BREAK, 0, "Break", kActionKeyType, false},
+	{"MENU", KEYCODE_MENU, 0, "Menu", kActionKeyType, false},
+		// Power Macintosh power key
+	{"POWER", KEYCODE_POWER, 0, "Power", kActionKeyType, false},
+		// Some european keyboards
+	{"EURO", KEYCODE_EURO, 0, "Euro", kActionKeyType, false},
+		// Atari keyboard has Undo
+	{"UNDO", KEYCODE_UNDO, 0, "Undo", kActionKeyType, false},
+	{0, KEYCODE_INVALID, 0, 0, kGenericKeyType, false}
+};
+
+struct Mod {
+	byte flag;
+	const char *id;
+	const char *desc;
+	bool shiftable;
+};
+
+static const Mod modifiers[] = {
+	{ 0, "", "", false },
+	{ KBD_CTRL, "C+", "Ctrl+", false },
+	{ KBD_ALT, "A+", "Alt+", false },
+	{ KBD_SHIFT, "", "", true },
+	{ KBD_CTRL | KBD_ALT, "C+A+", "Ctrl+Alt+", false },
+	{ KBD_SHIFT | KBD_CTRL, "S+C+", "Shift+Ctrl+", true },
+	{ KBD_SHIFT | KBD_CTRL | KBD_ALT, "C+A+", "Ctrl+Alt+", true },
+	{ 0, 0, 0, false }
+};
+#endif
+
+
+Common::HardwareKeySet *OSystem_SDL_SamsungTV::getHardwareKeySet() {
+#ifdef ENABLE_KEYMAPPER
+	HardwareKeySet *keySet = new HardwareKeySet();
+	const Key *key;
+	const Mod *mod;
+	char fullKeyId[50];
+	char fullKeyDesc[100];
+	uint16 ascii;
+
+	for (mod = modifiers; mod->id; mod++) {
+		for (key = keys; key->hwId; key++) {
+			ascii = key->ascii;
+
+			if (mod->shiftable && key->shiftable) {
+				snprintf(fullKeyId, 50, "%s%c", mod->id, toupper(key->hwId[0]));
+				snprintf(fullKeyDesc, 100, "%s%c", mod->desc, toupper(key->desc[0]));
+				ascii = toupper(key->ascii);
+			} else if (mod->shiftable) {
+				snprintf(fullKeyId, 50, "S+%s%s", mod->id, key->hwId);
+				snprintf(fullKeyDesc, 100, "Shift+%s%s", mod->desc, key->desc);
+			} else {
+				snprintf(fullKeyId, 50, "%s%s", mod->id, key->hwId);
+				snprintf(fullKeyDesc, 100, "%s%s", mod->desc, key->desc);
+			}
+
+			keySet->addHardwareKey(new HardwareKey(fullKeyId, KeyState(key->keycode, ascii, mod->flag), fullKeyDesc, key->preferredAction ));
+		}
+	}
+
+	return keySet;
+
+#else
+	return 0;
+#endif
+}
+
+#endif


Property changes on: scummvm/trunk/backends/platform/samsungtv/hardwarekeys.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/main.cpp
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/main.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/main.cpp	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,91 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/main.cpp $
+ * $Id: main.cpp 43636 2009-08-22 12:35:49Z sev $
+ *
+ */
+
+#include "backends/platform/samsungtv/sdl.h"
+#include "backends/plugins/sdl/sdl-provider.h"
+#include "base/main.h"
+
+#if defined(SAMSUNGTV)
+
+#include <unistd.h>
+
+extern "C" int Game_Main(char *path, char *) {
+	chdir(path);
+
+	//
+	// Set up redirects for stdout/stderr under Windows and Symbian.
+	// Code copied from SDL_main.
+	//
+/*
+	// Symbian does not like any output to the console through any *print* function
+	char STDOUT_FILE[256], STDERR_FILE[256]; // shhh, don't tell anybody :)
+	strcpy(STDOUT_FILE, "/dtv/usb/sda1/");
+	strcpy(STDERR_FILE, "/dtv/usb/sda1/");
+	strcat(STDOUT_FILE, "scummvm.stdout.txt");
+	strcat(STDERR_FILE, "scummvm.stderr.txt");
+*/
+	/* Flush the output in case anything is queued */
+/*	fclose(stdout);
+	fclose(stderr);
+*/
+	/* Redirect standard input and standard output */
+//	FILE *newfp = freopen(STDOUT_FILE, "w", stdout);
+//	if (newfp == NULL) {	/* This happens on NT */
+/*#if !defined(stdout)
+		stdout = fopen(STDOUT_FILE, "w");
+#else
+		newfp = fopen(STDOUT_FILE, "w");
+		if (newfp) {
+			*stdout = *newfp;
+		}
+#endif
+	}
+	newfp = freopen(STDERR_FILE, "w", stderr);
+	if (newfp == NULL) {*/	/* This happens on NT */
+/*#if !defined(stderr)
+		stderr = fopen(STDERR_FILE, "w");
+#else
+		newfp = fopen(STDERR_FILE, "w");
+		if (newfp) {
+			*stderr = *newfp;
+		}
+#endif
+	}
+	setbuf(stderr, NULL);*/			/* No buffering */
+
+	g_system = new OSystem_SDL_SamsungTV();
+	assert(g_system);
+
+#ifdef DYNAMIC_MODULES
+	PluginManager::instance().addPluginProvider(new SDLPluginProvider());
+#endif
+
+	// Invoke the actual ScummVM main entry point:
+	int res = scummvm_main(0, 0);
+	g_system->quit();	// TODO: Consider removing / replacing this!
+	return res;
+}
+
+#endif


Property changes on: scummvm/trunk/backends/platform/samsungtv/main.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/module.mk
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/module.mk	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/module.mk	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,14 @@
+MODULE := backends/platform/samsungtv
+
+MODULE_OBJS := \
+	events.o \
+	graphics.o \
+	hardwarekeys.o \
+	main.o \
+	sdl.o
+
+MODULE_DIRS += \
+	backends/platform/samsungtv/
+
+# We don't use the rules.mk here on purpose
+OBJS := $(addprefix $(MODULE)/, $(MODULE_OBJS)) $(OBJS)


Property changes on: scummvm/trunk/backends/platform/samsungtv/module.mk
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/sdl.cpp
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/sdl.cpp	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/sdl.cpp	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,427 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/sdl.cpp $
+ * $Id: sdl.cpp 44793 2009-10-08 19:41:38Z fingolfin $
+ *
+ */
+
+#include "backends/platform/samsungtv/sdl.h"
+#include "common/archive.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/EventRecorder.h"
+#include "common/util.h"
+
+#include "backends/saves/posix/posix-saves.h"
+#include "backends/timer/default/default-timer.h"
+#include "sound/mixer_intern.h"
+
+#include <time.h>	// for getTimeAndDate()
+
+#define SAMPLES_PER_SEC 22050
+
+/*
+ * Include header files needed for the getFilesystemFactory() method.
+ */
+#include "backends/fs/posix/posix-fs-factory.h"
+
+#if defined(SAMSUNGTV)
+
+#define DEFAULT_CONFIG_FILE "/dtv/usb/sda1/.scummvmrc"
+
+static Uint32 timer_handler(Uint32 interval, void *param) {
+	((DefaultTimerManager *)param)->handler();
+	return interval;
+}
+
+AspectRatio::AspectRatio(int w, int h) {
+	// TODO : Validation and so on...
+	// Currently, we just ensure the program don't instantiate non-supported aspect ratios
+	_kw = w;
+	_kh = h;
+}
+
+static const size_t AR_COUNT = 4;
+static const char*       desiredAspectRatioAsStrings[AR_COUNT] = {            "auto",            "4/3",            "16/9",            "16/10" };
+static const AspectRatio desiredAspectRatios[AR_COUNT]         = { AspectRatio(0, 0), AspectRatio(4,3), AspectRatio(16,9), AspectRatio(16,10) };
+static AspectRatio getDesiredAspectRatio() {
+	//TODO : We could parse an arbitrary string, if we code enough proper validation
+	Common::String desiredAspectRatio = ConfMan.get("desired_screen_aspect_ratio");
+
+	for (size_t i = 0; i < AR_COUNT; i++) {
+		assert(desiredAspectRatioAsStrings[i] != NULL);
+
+		if (!scumm_stricmp(desiredAspectRatio.c_str(), desiredAspectRatioAsStrings[i])) {
+			return desiredAspectRatios[i];
+		}
+	}
+	// TODO : Report a warning
+	return AspectRatio(0, 0);
+}
+
+void OSystem_SDL_SamsungTV::initBackend() {
+	assert(!_inited);
+
+	uint32 sdlFlags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER;
+
+	if (ConfMan.hasKey("disable_sdl_parachute"))
+		sdlFlags |= SDL_INIT_NOPARACHUTE;
+
+	if (SDL_Init(sdlFlags) == -1) {
+		error("Could not initialize SDL: %s", SDL_GetError());
+	}
+
+	_graphicsMutex = createMutex();
+
+	// Enable unicode support if possible
+	SDL_EnableUNICODE(1);
+
+	memset(&_oldVideoMode, 0, sizeof(_oldVideoMode));
+	memset(&_videoMode, 0, sizeof(_videoMode));
+	memset(&_transactionDetails, 0, sizeof(_transactionDetails));
+
+	_cksumValid = false;
+	_videoMode.mode = GFX_2XSAI;
+	_videoMode.scaleFactor = 2;
+	_videoMode.aspectRatioCorrection = ConfMan.getBool("aspect_ratio");
+	_videoMode.desiredAspectRatio = getDesiredAspectRatio();
+	_scalerProc = _2xSaI;
+	_scalerType = 0;
+	_modeFlags = 0;
+	_videoMode.fullscreen = true;
+
+
+	// Create the savefile manager, if none exists yet (we check for this to
+	// allow subclasses to provide their own).
+	if (_savefile == NULL) {
+	    _savefile = new POSIXSaveFileManager();
+	}
+
+	// Create and hook up the mixer, if none exists yet (we check for this to
+	// allow subclasses to provide their own).
+	if (_mixer == NULL) {
+		setupMixer();
+	}
+
+	// Create and hook up the timer manager, if none exists yet (we check for
+	// this to allow subclasses to provide their own).
+	if (_timer == NULL) {
+		// Note: We could implement a custom SDLTimerManager by using
+		// SDL_AddTimer. That might yield better timer resolution, but it would
+		// also change the semantics of a timer: Right now, ScummVM timers
+		// *never* run in parallel, due to the way they are implemented. If we
+		// switched to SDL_AddTimer, each timer might run in a separate thread.
+		// However, not all our code is prepared for that, so we can't just
+		// switch. Still, it's a potential future change to keep in mind.
+		_timer = new DefaultTimerManager();
+		_timerID = SDL_AddTimer(10, &timer_handler, _timer);
+	}
+
+	// Invoke parent implementation of this method
+	OSystem::initBackend();
+
+	_inited = true;
+}
+
+OSystem_SDL_SamsungTV::OSystem_SDL_SamsungTV()
+	:
+#ifdef USE_OSD
+	_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
+#endif
+	_hwscreen(0), _prehwscreen(0), _screen(0), _tmpscreen(0),
+	_screenFormat(Graphics::PixelFormat::createFormatCLUT8()),
+	_cursorFormat(Graphics::PixelFormat::createFormatCLUT8()),
+	_overlayVisible(false),
+	_overlayscreen(0), _tmpscreen2(0),
+	_samplesPerSec(0),
+	_scalerProc(0), _modeChanged(false), _screenChangeCount(0), _dirtyChecksums(0),
+	_mouseVisible(false), _mouseNeedsRedraw(false), _mouseData(0), _mouseSurface(0),
+	_mouseOrigSurface(0), _cursorTargetScale(1), _cursorPaletteDisabled(true),
+	_currentShakePos(0), _newShakePos(0),
+	_paletteDirtyStart(0), _paletteDirtyEnd(0),
+	_fsFactory(0),
+	_savefile(0),
+	_mixer(0),
+	_timer(0),
+	_screenIsLocked(false),
+	_graphicsMutex(0), _transactionMode(kTransactionNone) {
+
+	// allocate palette storage
+	_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
+	_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
+
+	_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
+
+	// reset mouse state
+	memset(&_km, 0, sizeof(_km));
+	memset(&_mouseCurState, 0, sizeof(_mouseCurState));
+
+	_inited = false;
+
+	_fsFactory = new POSIXFilesystemFactory();
+}
+
+OSystem_SDL_SamsungTV::~OSystem_SDL_SamsungTV() {
+	SDL_RemoveTimer(_timerID);
+	closeMixer();
+
+	free(_dirtyChecksums);
+	free(_currentPalette);
+	free(_cursorPalette);
+	free(_mouseData);
+
+	delete _savefile;
+	delete _timer;
+}
+
+uint32 OSystem_SDL_SamsungTV::getMillis() {
+	uint32 millis = SDL_GetTicks();
+	g_eventRec.processMillis(millis);
+	return millis;
+}
+
+void OSystem_SDL_SamsungTV::delayMillis(uint msecs) {
+	SDL_Delay(msecs);
+}
+
+void OSystem_SDL_SamsungTV::getTimeAndDate(TimeDate &td) const {
+	time_t curTime = time(0);
+	struct tm t = *localtime(&curTime);
+	td.tm_sec = t.tm_sec;
+	td.tm_min = t.tm_min;
+	td.tm_hour = t.tm_hour;
+	td.tm_mday = t.tm_mday;
+	td.tm_mon = t.tm_mon;
+	td.tm_year = t.tm_year;
+}
+
+Common::TimerManager *OSystem_SDL_SamsungTV::getTimerManager() {
+	assert(_timer);
+	return _timer;
+}
+
+Common::SaveFileManager *OSystem_SDL_SamsungTV::getSavefileManager() {
+	assert(_savefile);
+	return _savefile;
+}
+
+FilesystemFactory *OSystem_SDL_SamsungTV::getFilesystemFactory() {
+	assert(_fsFactory);
+	return _fsFactory;
+}
+
+void OSystem_SDL_SamsungTV::addSysArchivesToSearchSet(Common::SearchSet &s, int priority) {
+	// 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(".");
+	if (dataNode.exists() && dataNode.isDirectory()) {
+		s.add(DATA_PATH, new Common::FSDirectory(dataNode, 4), priority);
+	}
+}
+
+
+static Common::String getDefaultConfigFileName() {
+	char configFile[MAXPATHLEN];
+	strcpy(configFile, DEFAULT_CONFIG_FILE);
+	return configFile;
+}
+
+Common::SeekableReadStream *OSystem_SDL_SamsungTV::createConfigReadStream() {
+	Common::FSNode file(getDefaultConfigFileName());
+	return file.createReadStream();
+}
+
+Common::WriteStream *OSystem_SDL_SamsungTV::createConfigWriteStream() {
+	Common::FSNode file(getDefaultConfigFileName());
+	return file.createWriteStream();
+}
+
+void OSystem_SDL_SamsungTV::setWindowCaption(const char *caption) {
+}
+
+bool OSystem_SDL_SamsungTV::hasFeature(Feature f) {
+	return
+		(f == kFeatureAutoComputeDirtyRects) ||
+		(f == kFeatureCursorHasPalette);
+}
+
+void OSystem_SDL_SamsungTV::setFeatureState(Feature f, bool enable) {
+	switch (f) {
+	case kFeatureAspectRatioCorrection:
+		setAspectRatioCorrection(enable);
+		break;
+	case kFeatureAutoComputeDirtyRects:
+		if (enable)
+			_modeFlags |= DF_WANT_RECT_OPTIM;
+		else
+			_modeFlags &= ~DF_WANT_RECT_OPTIM;
+		break;
+	default:
+		break;
+	}
+}
+
+bool OSystem_SDL_SamsungTV::getFeatureState(Feature f) {
+	assert (_transactionMode == kTransactionNone);
+
+	switch (f) {
+	case kFeatureAspectRatioCorrection:
+		return _videoMode.aspectRatioCorrection;
+	case kFeatureAutoComputeDirtyRects:
+		return _modeFlags & DF_WANT_RECT_OPTIM;
+	default:
+		return false;
+	}
+}
+
+void OSystem_SDL_SamsungTV::quit() {
+	unloadGFXMode();
+	deleteMutex(_graphicsMutex);
+
+	SDL_RemoveTimer(_timerID);
+	closeMixer();
+
+	free(_dirtyChecksums);
+	free(_currentPalette);
+	free(_cursorPalette);
+	free(_mouseData);
+
+	delete _timer;
+
+	SDL_Quit();
+
+	// Even Manager requires save manager for storing
+	// recorded events
+	delete getEventManager();
+	delete _savefile;
+}
+
+void OSystem_SDL_SamsungTV::setupIcon() {
+}
+
+OSystem::MutexRef OSystem_SDL_SamsungTV::createMutex(void) {
+	return (MutexRef)SDL_CreateMutex();
+}
+
+void OSystem_SDL_SamsungTV::lockMutex(MutexRef mutex) {
+	SDL_mutexP((SDL_mutex *) mutex);
+}
+
+void OSystem_SDL_SamsungTV::unlockMutex(MutexRef mutex) {
+	SDL_mutexV((SDL_mutex *) mutex);
+}
+
+void OSystem_SDL_SamsungTV::deleteMutex(MutexRef mutex) {
+	SDL_DestroyMutex((SDL_mutex *) mutex);
+}
+
+void OSystem_SDL_SamsungTV::mixCallback(void *sys, byte *samples, int len) {
+	OSystem_SDL_SamsungTV *this_ = (OSystem_SDL_SamsungTV *)sys;
+	assert(this_);
+	assert(this_->_mixer);
+
+	this_->_mixer->mixCallback(samples, len);
+}
+
+void OSystem_SDL_SamsungTV::setupMixer() {
+	SDL_AudioSpec desired;
+
+	// Determine the desired output sampling frequency.
+	_samplesPerSec = 0;
+	if (ConfMan.hasKey("output_rate"))
+		_samplesPerSec = ConfMan.getInt("output_rate");
+	if (_samplesPerSec <= 0)
+		_samplesPerSec = SAMPLES_PER_SEC;
+
+	// Determine the sample buffer size. We want it to store enough data for
+	// about 1/16th of a second. Note that it must be a power of two.
+	// So e.g. at 22050 Hz, we request a sample buffer size of 2048.
+	int samples = 8192;
+	while (16 * samples >= _samplesPerSec) {
+		samples >>= 1;
+	}
+
+	memset(&desired, 0, sizeof(desired));
+	desired.freq = _samplesPerSec;
+	desired.format = AUDIO_S16SYS;
+	desired.channels = 2;
+	desired.samples = (uint16)samples;
+	desired.callback = mixCallback;
+	desired.userdata = this;
+
+	// Create the mixer instance
+	assert(!_mixer);
+	_mixer = new Audio::MixerImpl(this);
+	assert(_mixer);
+
+	if (SDL_OpenAudio(&desired, &_obtainedRate) != 0) {
+		warning("Could not open audio device: %s", SDL_GetError());
+		_samplesPerSec = 0;
+		_mixer->setReady(false);
+	} else {
+		// Note: This should be the obtained output rate, but it seems that at
+		// least on some platforms SDL will lie and claim it did get the rate
+		// even if it didn't. Probably only happens for "weird" rates, though.
+		_samplesPerSec = _obtainedRate.freq;
+		debug(1, "Output sample rate: %d Hz", _samplesPerSec);
+
+		// Tell the mixer that we are ready and start the sound processing
+		_mixer->setOutputRate(_samplesPerSec);
+		_mixer->setReady(true);
+
+		// start the sound system
+		SDL_PauseAudio(0);
+	}
+}
+
+void OSystem_SDL_SamsungTV::closeMixer() {
+	if (_mixer)
+		_mixer->setReady(false);
+
+	SDL_CloseAudio();
+
+	delete _mixer;
+	_mixer = 0;
+}
+
+Audio::Mixer *OSystem_SDL_SamsungTV::getMixer() {
+	assert(_mixer);
+	return _mixer;
+}
+
+bool OSystem_SDL_SamsungTV::openCD(int drive) {
+	return false;
+}
+
+void OSystem_SDL_SamsungTV::stopCD() {
+}
+
+void OSystem_SDL_SamsungTV::playCD(int track, int num_loops, int start_frame, int duration) {
+}
+
+bool OSystem_SDL_SamsungTV::pollCD() {
+	return false;
+}
+
+void OSystem_SDL_SamsungTV::updateCD() {
+}
+
+#endif


Property changes on: scummvm/trunk/backends/platform/samsungtv/sdl.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native

Added: scummvm/trunk/backends/platform/samsungtv/sdl.h
===================================================================
--- scummvm/trunk/backends/platform/samsungtv/sdl.h	                        (rev 0)
+++ scummvm/trunk/backends/platform/samsungtv/sdl.h	2009-11-09 14:29:53 UTC (rev 45775)
@@ -0,0 +1,436 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/backends/platform/sdl/sdl.h $
+ * $Id: sdl.h 44793 2009-10-08 19:41:38Z fingolfin $
+ *
+ */
+
+#ifndef SDL_COMMON_H
+#define SDL_SAMSUNGTV_COMMON_H
+
+#include <SDL.h>
+
+#include "backends/base-backend.h"
+#include "graphics/scaler.h"
+
+#if defined(SAMSUNGTV)
+
+namespace Audio {
+	class MixerImpl;
+}
+
+#define USE_OSD	1
+
+enum {
+	GFX_NORMAL = 0,
+	GFX_DOUBLESIZE = 1,
+	GFX_TRIPLESIZE = 2,
+	GFX_2XSAI = 3,
+	GFX_SUPER2XSAI = 4,
+	GFX_SUPEREAGLE = 5,
+	GFX_ADVMAME2X = 6,
+	GFX_ADVMAME3X = 7,
+	GFX_HQ2X = 8,
+	GFX_HQ3X = 9,
+	GFX_TV2X = 10,
+	GFX_DOTMATRIX = 11
+};
+
+class AspectRatio {
+	int _kw, _kh;
+public:
+	AspectRatio() { _kw = _kh = 0; }
+	AspectRatio(int w, int h);
+ 
+	bool isAuto() const { return (_kw | _kh) == 0; }
+	
+	int kw() const { return _kw; }
+	int kh() const { return _kh; }
+};
+
+
+class OSystem_SDL_SamsungTV : public BaseBackend {
+public:
+	OSystem_SDL_SamsungTV();
+	virtual ~OSystem_SDL_SamsungTV();
+
+	virtual void initBackend();
+
+	void beginGFXTransaction();
+	TransactionError endGFXTransaction();
+
+#ifdef USE_RGB_COLOR
+	// Game screen
+	virtual Graphics::PixelFormat getScreenFormat() const { return _screenFormat; }
+
+	// Highest supported
+	virtual Common::List<Graphics::PixelFormat> getSupportedFormats();
+#endif
+
+	// Set the size and format of the video bitmap.
+	// Typically, 320x200 CLUT8
+	virtual void initSize(uint w, uint h, const Graphics::PixelFormat *format); // overloaded by CE backend
+
+	virtual int getScreenChangeID() const { return _screenChangeCount; }
+
+	// Set colors of the palette
+	void setPalette(const byte *colors, uint start, uint num);
+
+	// Get colors of the palette
+	void grabPalette(byte *colors, uint start, uint num);
+
+	// Draw a bitmap to screen.
+	// The screen will not be updated to reflect the new bitmap
+	virtual void copyRectToScreen(const byte *src, int pitch, int x, int y, int w, int h); // overloaded by CE backend (FIXME)
+
+	virtual Graphics::Surface *lockScreen();
+	virtual void unlockScreen();
+
+	// Update the dirty areas of the screen
+	void updateScreen();
+
+	// Either show or hide the mouse cursor
+	bool showMouse(bool visible);
+
+	// Warp the mouse cursor. Where set_mouse_pos() only informs the
+	// backend of the mouse cursor's current position, this function
+	// actually moves the cursor to the specified position.
+	virtual void warpMouse(int x, int y); // overloaded by CE backend (FIXME)
+
+	// Set the bitmap that's used when drawing the cursor.
+	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, uint32 keycolor, int cursorTargetScale, const Graphics::PixelFormat *format); // overloaded by CE backend (FIXME)
+
+	// Set colors of cursor palette
+	void setCursorPalette(const byte *colors, uint start, uint num);
+
+	// Disables or enables cursor palette
+	void disableCursorPalette(bool disable) {
+		_cursorPaletteDisabled = disable;
+		blitCursor();
+	}
+
+	// Shaking is used in SCUMM. Set current shake position.
+	void setShakePos(int shake_pos);
+
+	// Get the number of milliseconds since the program was started.
+	uint32 getMillis();
+
+	// Delay for a specified amount of milliseconds
+	void delayMillis(uint msecs);
+
+	// Get the next event.
+	// Returns true if an event was retrieved.
+	virtual bool pollEvent(Common::Event &event); // overloaded by CE backend
+
+	// Define all hardware keys for keymapper
+	virtual Common::HardwareKeySet *getHardwareKeySet();
+
+	// Set function that generates samples
+	virtual void setupMixer();
+	static void mixCallback(void *s, byte *samples, int len);
+
+	virtual void closeMixer();
+
+	virtual Audio::Mixer *getMixer();
+
+	// Poll CD status
+	// Returns true if cd audio is playing
+	bool pollCD();
+
+	// Play CD audio track
+	void playCD(int track, int num_loops, int start_frame, int duration);
+
+	// Stop CD audio track
+	void stopCD();
+
+	// Update CD audio status
+	void updateCD();
+
+	// Quit
+	virtual void quit(); // overloaded by CE backend
+
+	virtual void getTimeAndDate(TimeDate &t) const;
+	virtual Common::TimerManager *getTimerManager();
+
+	// Mutex handling
+	MutexRef createMutex();
+	void lockMutex(MutexRef mutex);
+	void unlockMutex(MutexRef mutex);
+	void deleteMutex(MutexRef mutex);
+
+	// Overlay
+	virtual Graphics::PixelFormat getOverlayFormat() const { return _overlayFormat; }
+
+	virtual void showOverlay();
+	virtual void hideOverlay();
+	virtual void clearOverlay();
+	virtual void grabOverlay(OverlayColor *buf, int pitch);
+	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h);
+	virtual int16 getHeight();
+	virtual int16 getWidth();
+	virtual int16 getOverlayHeight()  { return _videoMode.overlayHeight; }
+	virtual int16 getOverlayWidth()   { return _videoMode.overlayWidth; }
+
+	virtual const GraphicsMode *getSupportedGraphicsModes() const;
+	virtual int getDefaultGraphicsMode() const;
+	virtual bool setGraphicsMode(int mode);
+	virtual int getGraphicsMode() const;
+
+	virtual void setWindowCaption(const char *caption);
+	virtual bool openCD(int drive);
+
+	virtual bool hasFeature(Feature f);
+	virtual void setFeatureState(Feature f, bool enable);
+	virtual bool getFeatureState(Feature f);
+	virtual void preprocessEvents(SDL_Event *event) {};
+
+#ifdef USE_OSD
+	void displayMessageOnOSD(const char *msg);
+#endif
+
+	virtual Common::SaveFileManager *getSavefileManager();
+	virtual FilesystemFactory *getFilesystemFactory();
+	virtual void addSysArchivesToSearchSet(Common::SearchSet &s, int priority = 0);
+
+	virtual Common::SeekableReadStream *createConfigReadStream();
+	virtual Common::WriteStream *createConfigWriteStream();
+
+protected:
+	bool _inited;
+	SDL_AudioSpec _obtainedRate;
+
+#ifdef USE_OSD
+	SDL_Surface *_osdSurface;
+	Uint8 _osdAlpha;			// Transparency level of the OSD
+	uint32 _osdFadeStartTime;	// When to start the fade out
+	enum {
+		kOSDFadeOutDelay = 2 * 1000,	// Delay before the OSD is faded out (in milliseconds)
+		kOSDFadeOutDuration = 500,		// Duration of the OSD fade out (in milliseconds)
+		kOSDColorKey = 1,
+		kOSDInitialAlpha = 80			// Initial alpha level, in percent
+	};
+#endif
+
+	// hardware screen
+	SDL_Surface *_hwscreen, *_prehwscreen;
+
+	// unseen game screen
+	SDL_Surface *_screen;
+#ifdef USE_RGB_COLOR
+	Graphics::PixelFormat _screenFormat;
+	Graphics::PixelFormat _cursorFormat;
+#endif
+
+	// temporary screen (for scalers)
+	SDL_Surface *_tmpscreen;
+	SDL_Surface *_tmpscreen2;
+
+	// overlay
+	SDL_Surface *_overlayscreen;
+	bool _overlayVisible;
+	Graphics::PixelFormat _overlayFormat;
+
+	// Audio
+	int _samplesPerSec;
+
+	enum {
+		DF_WANT_RECT_OPTIM			= 1 << 0
+	};
+
+	enum {
+		kTransactionNone = 0,
+		kTransactionActive = 1,
+		kTransactionRollback = 2
+	};
+
+	struct TransactionDetails {
+		bool sizeChanged;
+		bool needHotswap;
+		bool needUpdatescreen;
+		bool normal1xScaler;
+#ifdef USE_RGB_COLOR
+		bool formatChanged;
+#endif
+	};
+	TransactionDetails _transactionDetails;
+
+	struct VideoState {
+		bool setup;
+
+		bool fullscreen;
+		bool aspectRatioCorrection;
+		AspectRatio desiredAspectRatio;
+
+		int mode;
+		int scaleFactor;
+
+		int screenWidth, screenHeight;
+		int overlayWidth, overlayHeight;
+		int hardwareWidth, hardwareHeight;
+#ifdef USE_RGB_COLOR
+		Graphics::PixelFormat format;
+#endif
+	};
+	VideoState _videoMode, _oldVideoMode;
+
+	virtual void setGraphicsModeIntern(); // overloaded by CE backend
+
+	/** Force full redraw on next updateScreen */
+	bool _forceFull;
+	ScalerProc *_scalerProc;
+	int _scalerType;
+	int _transactionMode;
+
+	bool _screenIsLocked;
+	Graphics::Surface _framebuffer;
+
+	/** Current video mode flags (see DF_* constants) */
+	uint32 _modeFlags;
+	bool _modeChanged;
+	int _screenChangeCount;
+
+	enum {
+		NUM_DIRTY_RECT = 100,
+		MAX_SCALING = 3
+	};
+
+	// Dirty rect management
+	SDL_Rect _dirtyRectList[NUM_DIRTY_RECT];
+	int _numDirtyRects;
+	uint32 *_dirtyChecksums;
+	bool _cksumValid;
+	int _cksumNum;
+
+	// Keyboard mouse emulation.  Disabled by fingolfin 2004-12-18.
+	// I am keeping the rest of the code in for now, since the joystick
+	// code (or rather, "hack") uses it, too.
+	struct KbdMouse {
+		int16 x, y, x_vel, y_vel, x_max, y_max, x_down_count, y_down_count;
+		uint32 last_time, delay_time, x_down_time, y_down_time;
+	};
+
+	struct MousePos {
+		// The mouse position, using either virtual (game) or real
+		// (overlay) coordinates.
+		int16 x, y;
+
+		// The size and hotspot of the original cursor image.
+		int16 w, h;
+		int16 hotX, hotY;
+
+		// The size and hotspot of the pre-scaled cursor image, in real
+		// coordinates.
+		int16 rW, rH;
+		int16 rHotX, rHotY;
+
+		// The size and hotspot of the pre-scaled cursor image, in game
+		// coordinates.
+		int16 vW, vH;
+		int16 vHotX, vHotY;
+
+		MousePos() : x(0), y(0), w(0), h(0), hotX(0), hotY(0),
+		             rW(0), rH(0), rHotX(0), rHotY(0), vW(0), vH(0),
+		             vHotX(0), vHotY(0)
+			{ }
+	};
+
+	// mouse
+	KbdMouse _km;
+	bool _mouseVisible;
+	bool _mouseNeedsRedraw;
+	byte *_mouseData;
+	SDL_Rect _mouseBackup;
+	MousePos _mouseCurState;
+	byte _mouseKeyColor;
+	int _cursorTargetScale;
+	bool _cursorPaletteDisabled;
+	SDL_Surface *_mouseOrigSurface;
+	SDL_Surface *_mouseSurface;
+	enum {
+		kMouseColorKey = 1
+	};
+
+	// Shake mode
+	int _currentShakePos;
+	int _newShakePos;
+
+	// Palette data
+	SDL_Color *_currentPalette;
+	uint _paletteDirtyStart, _paletteDirtyEnd;
+
+	// Cursor palette data
+	SDL_Color *_cursorPalette;
+
+	/**
+	 * Mutex which prevents multiple threads from interfering with each other
+	 * when accessing the screen.
+	 */
+	MutexRef _graphicsMutex;
+
+	FilesystemFactory *_fsFactory;
+	Common::SaveFileManager *_savefile;
+	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); // overloaded by CE backend
+
+	virtual void drawMouse(); // overloaded by CE backend
+	virtual void undrawMouse(); // overloaded by CE backend (FIXME)
+	virtual void blitCursor(); // overloaded by CE backend (FIXME)
+
+	/** Set the position of the virtual mouse cursor. */

@@ Diff output truncated at 100000 characters. @@

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