Index: backends/sdl/graphics.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/graphics.cpp,v
retrieving revision 1.24
diff -u -r1.24 graphics.cpp
--- backends/sdl/graphics.cpp	6 Jan 2005 21:15:50 -0000	1.24
+++ backends/sdl/graphics.cpp	17 Feb 2005 22:38:34 -0000
@@ -42,6 +42,16 @@
 	{0, 0, 0}
 };
 
+// Table of relative scalers magnitudes
+// [definedScale-1][_scaleFactor-1]
+static ScalerProc *scalersMagn[3][3] = {
+	{ Normal1x, AdvMame2x, AdvMame3x },
+	{ Normal1x, Normal1x, Normal1o5x },
+	{ Normal1x, Normal1x, Normal1x }
+};
+
+static int cursorStretch200To240(uint8 *buf, uint32 pitch, int width, int height, int srcX, int srcY, int origSrcY);
+
 const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
 	return s_supportedGraphicsModes;
 }
@@ -367,6 +377,9 @@
 	SDL_FreeSurface(old_screen);
 	SDL_FreeSurface(old_tmpscreen);
 
+	// Update cursor to new scale
+	blitCursor();
+
 	// Blit everything to the screen
 	internUpdateScreen();
 	
@@ -399,9 +412,6 @@
 		_forceFull = true;
 	}
 
-	// Make sure the mouse is drawn, if it should be drawn.
-	drawMouse();
-	
 	// Check whether the palette was changed in the meantime and update the
 	// screen surface accordingly. 
 	if (_paletteDirtyEnd != 0) {
@@ -434,6 +444,8 @@
 	}
 #endif
 
+	undrawMouse();
+
 	// Force a full redraw if requested
 	if (_forceFull) {
 		_numDirtyRects = 1;
@@ -527,9 +539,14 @@
 			SDL_BlitSurface(_osdSurface, 0, _hwscreen, 0);
 		}
 #endif
-
+		drawMouse();
+		
 		// Finally, blit all our changes to the screen
 		SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
+	} else {
+		drawMouse();
+		if (_numDirtyRects)
+			SDL_UpdateRects(_hwscreen, _numDirtyRects, _dirtyRectList);
 	}
 
 	_numDirtyRects = 0;
@@ -562,8 +579,6 @@
 		assert(_hwscreen != 0);
 		_fullscreen ^= true;
 		
-		undrawMouse();
-
 #if defined(MACOSX) && !SDL_VERSION_ATLEAST(1, 2, 6)
 		// On OS X, SDL_WM_ToggleFullScreen is currently not implemented. Worse,
 		// before SDL 1.2.6 it always returned -1 (which would indicate a
@@ -672,9 +687,6 @@
 		addDirtyRect(x, y, w, h);
 	}
 
-	/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
-	undrawMouse();
-
 	// Try to lock the screen surface
 	if (SDL_LockSurface(_screen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
@@ -696,10 +708,19 @@
 }
 
 
-void OSystem_SDL::addDirtyRect(int x, int y, int w, int h) {
+void OSystem_SDL::addDirtyRect(int x, int y, int w, int h, bool mouseRect) {
 	if (_forceFull)
 		return;
 
+ 	if (mouseRect) {
+ 		SDL_Rect *r = &_dirtyRectList[_numDirtyRects++];
+ 		r->x = x;
+ 		r->y = y;
+ 		r->w = w;
+ 		r->h = h;
+ 		return;
+ 	}
+
 	if (_numDirtyRects == NUM_DIRTY_RECT)
 		_forceFull = true;
 	else {
@@ -846,6 +867,27 @@
 
 	if (start + num > _paletteDirtyEnd)
 		_paletteDirtyEnd = start + num;
+
+	// Some games blink cursors with palette
+	if (!_overlayVisible && !_cursorHasOwnPalette)
+		blitCursor();
+}
+
+void OSystem_SDL::setCursorPalette(const byte *colors, uint start, uint num) {
+	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;
+	}
+
+	_cursorHasOwnPalette = true;
+
+	if (!_overlayVisible)
+		blitCursor();
 }
 
 void OSystem_SDL::setShakePos(int shake_pos) {
@@ -862,9 +904,6 @@
 void OSystem_SDL::showOverlay() {
 	assert (_transactionMode == kTransactionNone);
 
-	// hide the mouse
-	undrawMouse();
-
 	_overlayVisible = true;
 	clearOverlay();
 }
@@ -872,9 +911,6 @@
 void OSystem_SDL::hideOverlay() {
 	assert (_transactionMode == kTransactionNone);
 
-	// hide the mouse
-	undrawMouse();
-
 	_overlayVisible = false;
 	_forceFull = true;
 }
@@ -887,9 +923,6 @@
 	
 	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
 	
-	// hide the mouse
-	undrawMouse();
-
 	// Clear the overlay by making the game screen "look through" everywhere.
 	SDL_Rect src, dst;
 	src.x = src.y = 0;
@@ -911,9 +944,6 @@
 	if (_tmpscreen == NULL)
 		return;
 
-	// hide the mouse
-	undrawMouse();
-
 	if (SDL_LockSurface(_tmpscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
@@ -964,9 +994,6 @@
 	_cksumValid = false;
 	addDirtyRect(x, y, w, h);
 
-	/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
-	undrawMouse();
-
 	if (SDL_LockSurface(_tmpscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
@@ -1000,17 +1027,13 @@
 	bool last = _mouseVisible;
 	_mouseVisible = visible;
 
-	if (visible)
-		drawMouse();
-	else
-		undrawMouse();
+	updateScreen();
 
 	return last;
 }
 
 void OSystem_SDL::setMousePos(int x, int y) {
 	if (x != _mouseCurState.x || y != _mouseCurState.y) {
-		undrawMouse();
 		_mouseCurState.x = x;
 		_mouseCurState.y = y;
 		updateScreen();
@@ -1032,187 +1055,236 @@
 	}
 }
 	
-void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor) {
-
-	undrawMouse();
-
-	assert(w <= MAX_MOUSE_W);
-	assert(h <= MAX_MOUSE_H);
-	_mouseCurState.w = w;
-	_mouseCurState.h = h;
-
+void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale) {
 	_mouseHotspotX = hotspot_x;
 	_mouseHotspotY = hotspot_y;
 
 	_mouseKeyColor = keycolor;
 
+ 	_cursorTargetScale = cursorTargetScale;
+ 
+ 	if (_mouseCurState.w != (int)w || _mouseCurState.h != (int)h) {
+ 		_mouseCurState.w = w;
+ 		_mouseCurState.h = h;
+ 
+ 		if (_mouseOrigSurface)
+ 			SDL_FreeSurface(_mouseOrigSurface); 
+ 
+		// Allocate bigger surface because AdvMame2x adds black pixel at [0,0]
+ 		_mouseOrigSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+ 						_mouseCurState.w + 2,
+ 						_mouseCurState.h + 2,
+ 						16,
+ 						_hwscreen->format->Rmask,
+ 						_hwscreen->format->Gmask,
+ 						_hwscreen->format->Bmask,
+ 						_hwscreen->format->Amask);
+ 
+ 		if (_mouseOrigSurface == NULL)
+ 			error("allocating _mouseOrigSurface failed");
+ 		SDL_SetColorKey(_mouseOrigSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+ 	}
+ 
 	free(_mouseData);
 
 	_mouseData = (byte *)malloc(w * h);
 	memcpy(_mouseData, buf, w * h);
+	blitCursor();
 }
 
-void OSystem_SDL::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::drawMouse() {
-	if (_mouseDrawn || !_mouseVisible || !_mouseData)
-		return;
-
-	int x = _mouseCurState.x - _mouseHotspotX;
-	int y = _mouseCurState.y - _mouseHotspotY;
-	int w = _mouseCurState.w;
-	int h = _mouseCurState.h;
+void OSystem_SDL::blitCursor() {
+	byte *dstPtr;
+	const byte *srcPtr = _mouseData;
 	byte color;
-	const byte *src = _mouseData;		// Image representing the mouse
-	
-	// clip the mouse rect, and addjust the src pointer accordingly
-	if (x < 0) {
-		w += x;
-		src -= x;
-		x = 0;
-	}
-	if (y < 0) {
-		h += y;
-		src -= y * _mouseCurState.w;
-		y = 0;
+	int w, h;
+  
+	if (!_mouseOrigSurface)
+ 		return;
+  
+	w = _mouseCurState.w;
+	h = _mouseCurState.h;
+  
+	SDL_LockSurface(_mouseOrigSurface);
+
+	// Make whole surface transparent
+	for (int i = 0; i < h + 2; i++) {
+		dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch * i;
+		for (int j = 0; j < w + 2; j++) {
+			*(uint16 *)dstPtr = kMouseColorKey;
+			dstPtr += 2;
+		}
 	}
 
-	if (w > _screenWidth - x)
-		w = _screenWidth - x;
-	if (h > _screenHeight - y)
-		h = _screenHeight - y;
-
-	// Quick check to see if anything has to be drawn at all
-	if (w <= 0 || h <= 0)
-		return;
-
-	// Draw the mouse cursor; backup the covered area in "bak"
-	if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
-		error("SDL_LockSurface failed: %s", SDL_GetError());
-
-	// Mark as dirty
-	addDirtyRect(x, y, w, h);
-
-	if (!_overlayVisible) {
-		byte *bak = _mouseBackup;		// Surface used to backup the area obscured by the mouse
-		byte *dst;					// Surface we are drawing into
-	
-		dst = (byte *)_screen->pixels + y * _screenWidth + x;
-		while (h > 0) {
-			int width = w;
-			while (width > 0) {
-				*bak++ = *dst;
-				color = *src++;
-				if (color != _mouseKeyColor)	// transparent, don't draw
-					*dst = color;
-				dst++;
-				width--;
+	// Draw from [1,1] since AdvMame2x adds artefact at 0,0
+	dstPtr = (byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2;
+
+	for (int i = 0; i < h; i++) {
+		for (int j = 0; j < w; j++) {
+			color = *srcPtr;
+			if (color != _mouseKeyColor) {	// transparent, don't draw
+				if (_cursorHasOwnPalette && !_overlayVisible)
+					*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, 
+								   _cursorPalette[color].r, _cursorPalette[color].g, 
+															   _cursorPalette[color].b);
+				else
+					*(uint16 *)dstPtr = SDL_MapRGB(_mouseOrigSurface->format, 
+								   _currentPalette[color].r, _currentPalette[color].g,
+												   				_currentPalette[color].b);
 			}
-			src += _mouseCurState.w - w;
-			bak += MAX_MOUSE_W - w;
-			dst += _screenWidth - w;
-			h--;
+			dstPtr += 2;
+			srcPtr++;
 		}
-	
+		dstPtr += _mouseOrigSurface->pitch - w * 2;
+  	}
+
+	int hW, hH, hH1;
+
+	if (_cursorTargetScale >= _scaleFactor) {
+		hW = w;
+		hH = hH1 = h;
 	} else {
-		uint16 *bak = (uint16 *)_mouseBackup;	// Surface used to backup the area obscured by the mouse
-		byte *dst;					// Surface we are drawing into
-	
-		dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
-		while (h > 0) {
-			int width = w;
-			while (width > 0) {
-				*bak++ = *(uint16 *)dst;
-				color = *src++;
-				if (color != 0xFF)	// 0xFF = transparent, don't draw
-					*(uint16 *)dst = RGBToColor(_currentPalette[color].r, _currentPalette[color].g, _currentPalette[color].b);
-				dst += 2;
-				width--;
-			}
-			src += _mouseCurState.w - w;
-			bak += MAX_MOUSE_W - w;
-			dst += _tmpscreen->pitch - w * 2;
-			h--;
-		}
+		hW = w * _scaleFactor / _cursorTargetScale;
+		hH = hH1 = h * _scaleFactor / _cursorTargetScale;
+  	}
+  
+	if (_adjustAspectRatio) {
+		hH = real2Aspect(hH - 1) + 1;
+	}
+  
+	if (_mouseCurState.hW != hW || _mouseCurState.hH != hH) {
+		_mouseCurState.hW = hW;
+		_mouseCurState.hH = hH;
+  
+		if (_mouseSurface)
+			SDL_FreeSurface(_mouseSurface); 
+  
+		_mouseSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_mouseCurState.hW,
+						_mouseCurState.hH,
+						16,
+						_hwscreen->format->Rmask,
+						_hwscreen->format->Gmask,
+						_hwscreen->format->Bmask,
+						_hwscreen->format->Amask);
+  
+		if (_mouseSurface == NULL)
+			error("allocating _mouseSurface failed");
+
+		SDL_SetColorKey(_mouseSurface, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kMouseColorKey);
+  	}
+  
+	SDL_LockSurface(_mouseSurface);
+	(scalersMagn[_cursorTargetScale-1][_scaleFactor-1])((byte *)_mouseOrigSurface->pixels + _mouseOrigSurface->pitch + 2,
+		_mouseOrigSurface->pitch, (byte *)_mouseSurface->pixels, _mouseSurface->pitch,
+			  _mouseCurState.w, _mouseCurState.h);
+
+	if (_adjustAspectRatio)
+		cursorStretch200To240((uint8 *)_mouseSurface->pixels, _mouseSurface->pitch, hW, hH1, 0, 0, 0);
+  
+	SDL_UnlockSurface(_mouseSurface);
+	SDL_UnlockSurface(_mouseOrigSurface);
+}
+
+// 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;
 	}
 
-	SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
+	return 1 + maxDstY - srcY;
+}
 
-	// Finally, set the flag to indicate the mouse has been drawn
-	_mouseDrawn = true;
+void OSystem_SDL::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::undrawMouse() {
-	assert (_transactionMode == kTransactionNone || _transactionMode == kTransactionCommit);
-
-	if (!_mouseDrawn)
-		return;
-	_mouseDrawn = false;
-
-	int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
-	int old_mouse_y = _mouseCurState.y - _mouseHotspotY;
-	int old_mouse_w = _mouseCurState.w;
-	int old_mouse_h = _mouseCurState.h;
-
-	// clip the mouse rect, and addjust the src pointer accordingly
-	if (old_mouse_x < 0) {
-		old_mouse_w += old_mouse_x;
-		old_mouse_x = 0;
-	}
-	if (old_mouse_y < 0) {
-		old_mouse_h += old_mouse_y;
-		old_mouse_y = 0;
-	}
-
-	if (old_mouse_w > _screenWidth - old_mouse_x)
-		old_mouse_w = _screenWidth - old_mouse_x;
-	if (old_mouse_h > _screenHeight - old_mouse_y)
-		old_mouse_h = _screenHeight - old_mouse_y;
-
-	// Quick check to see if anything has to be drawn at all
-	if (old_mouse_w <= 0 || old_mouse_h <= 0)
-		return;
+	if (_mouseBackup.w) {
+		if (_adjustAspectRatio)
+			addDirtyRect(_mouseBackup.x, aspect2Real(_mouseBackup.y), _mouseBackup.w,
+						   _mouseBackup.h);
+		else
+			addDirtyRect(_mouseBackup.x, _mouseBackup.y, _mouseBackup.w,
+						   _mouseBackup.h);
+	}
+}
 
-	if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
-		error("SDL_LockSurface failed: %s", SDL_GetError());
+void OSystem_SDL::drawMouse() {
+	if (!_mouseVisible) {
+		_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
+  		return;
+	}
+  
+	SDL_Rect src, dst;
+	bool scale;
 
-	int x, y;
-	if (!_overlayVisible) {
-		byte *dst, *bak = _mouseBackup;
-
-		// No need to do clipping here, since drawMouse() did that already
-		dst = (byte *)_screen->pixels + old_mouse_y * _screenWidth + old_mouse_x;
-		for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _screenWidth) {
-			for (x = 0; x < old_mouse_w; ++x) {
-				dst[x] = bak[x];
-			}
-		}
-	
-	} else {
+	scale = (_scaleFactor > _cursorTargetScale);
 
-		byte *dst;
-		uint16 *bak = (uint16 *)_mouseBackup;
-	
-		// No need to do clipping here, since drawMouse() did that already
-		dst = (byte *)_tmpscreen->pixels + (old_mouse_y + 1) * _tmpscreen->pitch + (old_mouse_x + 1) * 2;
-		for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _tmpscreen->pitch) {
-			for (x = 0; x < old_mouse_w; ++x) {
-				*((uint16 *)dst + x) = bak[x];
-			}
-		}
-	}
+	dst.x = _mouseCurState.x - _mouseHotspotX / _cursorTargetScale;
+	dst.y = _mouseCurState.y - _mouseHotspotY / _cursorTargetScale;
 
-	addDirtyRect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+	dst.w = _mouseCurState.hW;
+	dst.h = _mouseCurState.hH;
+	src.x = src.y = 0;
 
-	SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
+	// clip the mouse rect, and adjust the src pointer accordingly
+	int dx, dy;
+  
+	dx = dst.x; dy = dst.y;
+	dx = scale ? dst.x * _scaleFactor / _cursorTargetScale : dst.x;
+	dy = scale ? dst.y * _scaleFactor / _cursorTargetScale : dst.y;
+	if (_adjustAspectRatio)
+		dy = real2Aspect(dy);
+
+	if (dst.x < 0) {
+		dst.w += dx;
+		src.x -= dx;
+		dst.x = 0;
+	}
+	if (dst.y < 0) {
+		dst.h += dy;
+		src.y -= dy;
+		dst.y = 0;
+	}
+
+  	// Quick check to see if anything has to be drawn at all
+	if (dst.w <= 0 || dst.h <= 0)
+  		return;
+  
+	src.w = dst.w;
+	src.h = dst.h;
+  
+	if (_adjustAspectRatio)
+		dst.y = real2Aspect(dst.y);
+  
+	_mouseBackup.x = dst.x;
+	_mouseBackup.y = dst.y;
+	_mouseBackup.w = dst.w;
+	_mouseBackup.h = dst.h;
+  
+	dst.x *= _scaleFactor;
+	dst.y *= _scaleFactor;
+  
+	if (SDL_BlitSurface(_mouseSurface, &src, _hwscreen, &dst) != 0)
+		error("SDL_BlitSurface failed: %s", SDL_GetError());
+  
+	addDirtyRect(dst.x, dst.y, dst.w, dst.h, true);
 }
 
-
 #pragma mark -
 #pragma mark --- Mouse ---
 #pragma mark -
Index: backends/sdl/sdl-common.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl-common.h,v
retrieving revision 1.71
diff -u -r1.71 sdl-common.h
--- backends/sdl/sdl-common.h	1 Jan 2005 16:08:47 -0000	1.71
+++ backends/sdl/sdl-common.h	17 Feb 2005 22:38:40 -0000
@@ -82,7 +82,10 @@
 	virtual void warpMouse(int x, int y); // overloaded by CE backend
 
 	// Set the bitmap that's used when drawing the cursor.
-	void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor);
+	void setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor, int cursorTargetScale);
+
+	// Set colors of cursor palette
+	void setCursorPalette(const byte *colors, uint start, uint num);
 
 	// Shaking is used in SCUMM. Set current shake position.
 	void setShakePos(int shake_pos);
@@ -258,7 +261,8 @@
 	};
 
 	struct MousePos {
-		int16 x, y, w, h;
+		int16 x, y, w, h, hW, hH;
+		MousePos() : x(0), y(0), w(0), h(0), hW(0), hH(0) {}
 	};
 
 	// mouse
@@ -266,11 +270,18 @@
 	bool _mouseVisible;
 	bool _mouseDrawn;
 	byte *_mouseData;
-	byte *_mouseBackup;
+	SDL_Rect _mouseBackup;
 	MousePos _mouseCurState;
 	int16 _mouseHotspotX;
 	int16 _mouseHotspotY;
 	byte _mouseKeyColor;
+	int _cursorTargetScale;
+	bool _cursorHasOwnPalette;
+	SDL_Surface *_mouseOrigSurface;
+	SDL_Surface *_mouseSurface;
+	enum {
+		kMouseColorKey = 1
+	};
 
 	// joystick
 	SDL_Joystick *_joystick;
@@ -283,6 +294,9 @@
 	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.
@@ -293,10 +307,11 @@
 	void addDirtyRgnAuto(const byte *buf);
 	void makeChecksums(const byte *buf);
 	
-	virtual void addDirtyRect(int x, int y, int w, int h); // overloaded by CE backend
+	virtual void addDirtyRect(int x, int y, int w, int h, bool mouseRect = false); // overloaded by CE backend
 
 	virtual void drawMouse(); // overloaded by CE backend
 	virtual void undrawMouse(); // overloaded by CE backend
+	void blitCursor();
 	
 	/** Set the position of the virtual mouse cursor. */
 	void setMousePos(int x, int y);
Index: backends/sdl/sdl.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl.cpp,v
retrieving revision 1.78
diff -u -r1.78 sdl.cpp
--- backends/sdl/sdl.cpp	1 Jan 2005 16:08:47 -0000	1.78
+++ backends/sdl/sdl.cpp	17 Feb 2005 22:38:40 -0000
@@ -100,8 +100,9 @@
 	_tmpscreen(0), _overlayVisible(false),
 	_samplesPerSec(0),
 	_cdrom(0), _scalerProc(0), _modeChanged(false), _dirtyChecksums(0),
-	_mouseVisible(false), _mouseDrawn(false), _mouseData(0),
-	_mouseHotspotX(0), _mouseHotspotY(0),
+	_mouseVisible(false), _mouseDrawn(false), _mouseData(0), _mouseSurface(0),
+	_mouseOrigSurface(0), _mouseHotspotX(0), _mouseHotspotY(0), _cursorTargetScale(1),
+	_cursorHasOwnPalette(false),
 	_joystick(0),
 	_currentShakePos(0), _newShakePos(0),
 	_paletteDirtyStart(0), _paletteDirtyEnd(0),
@@ -109,9 +110,9 @@
 
 	// allocate palette storage
 	_currentPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
+	_cursorPalette = (SDL_Color *)calloc(sizeof(SDL_Color), 256);
 
-	// allocate the dirty rect storage
-	_mouseBackup = (byte *)malloc(MAX_MOUSE_W * MAX_MOUSE_H * MAX_SCALING * 2);
+	_mouseBackup.x = _mouseBackup.y = _mouseBackup.w = _mouseBackup.h = 0;
 
 	// reset mouse state
 	memset(&_km, 0, sizeof(_km));
@@ -123,7 +124,7 @@
 OSystem_SDL::~OSystem_SDL() {
 	free(_dirtyChecksums);
 	free(_currentPalette);
-	free(_mouseBackup);
+	free(_cursorPalette);
 	free(_mouseData);
 }
 
@@ -147,7 +148,8 @@
 	return
 		(f == kFeatureFullscreenMode) ||
 		(f == kFeatureAspectRatioCorrection) ||
-		(f == kFeatureAutoComputeDirtyRects);
+		(f == kFeatureAutoComputeDirtyRects) ||
+		(f == kFeatureCursorHasPalette);
 }
 
 void OSystem_SDL::setFeatureState(Feature f, bool enable) {
Index: common/scaler.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/common/scaler.cpp,v
retrieving revision 1.64
diff -u -r1.64 scaler.cpp
--- common/scaler.cpp	1 Jan 2005 16:08:49 -0000	1.64
+++ common/scaler.cpp	17 Feb 2005 22:38:40 -0000
@@ -169,6 +169,46 @@
 	}
 }
 
+#define INTERPOLATE		INTERPOLATE<bitFormat>
+#define Q_INTERPOLATE	Q_INTERPOLATE<bitFormat>
+
+/**
+ * Trivial nearest-neighbour 1.5x scaler.
+ */
+template<int bitFormat>
+void Normal1o5xTemplate(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
+							int width, int height) {
+	uint8 *r;
+	const uint32 dstPitch2 = dstPitch * 2;
+	const uint32 dstPitch3 = dstPitch * 3;
+	const uint32 srcPitch2 = srcPitch * 2;
+
+	assert(((int)dstPtr & 1) == 0);
+	while (height) {
+		r = dstPtr;
+		for (int i = 0; i < width; i += 2, r += 6) {
+			uint16 color0 = *(((const uint16 *)srcPtr) + i);
+			uint16 color1 = *(((const uint16 *)srcPtr) + i + 1);
+			uint16 color2 = *(((const uint16 *)(srcPtr + srcPitch)) + i);
+			uint16 color3 = *(((const uint16 *)(srcPtr + srcPitch)) + i + 1);
+
+			*(uint16 *)(r + 0) = color0;
+			*(uint16 *)(r + 2) = INTERPOLATE(color0, color1);
+			*(uint16 *)(r + 4) = color1;
+			*(uint16 *)(r + 0 + dstPitch) = INTERPOLATE(color0, color2);
+			*(uint16 *)(r + 2 + dstPitch) = Q_INTERPOLATE(color0, color1, color2, color3);
+			*(uint16 *)(r + 4 + dstPitch) = INTERPOLATE(color1, color3);
+			*(uint16 *)(r + 0 + dstPitch2) = color2;
+			*(uint16 *)(r + 2 + dstPitch2) = INTERPOLATE(color2, color3);
+			*(uint16 *)(r + 4 + dstPitch2) = color3;
+		}
+		srcPtr += srcPitch2;
+		dstPtr += dstPitch3;
+		height -= 2;
+	}
+}
+MAKE_WRAPPER(Normal1o5x)
+
 /**
  * The Scale2x filter, also known as AdvMame2x.
  * See also http://scale2x.sourceforge.net
Index: common/scaler.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/common/scaler.h,v
retrieving revision 1.27
diff -u -r1.27 scaler.h
--- common/scaler.h	1 Jan 2005 16:08:50 -0000	1.27
+++ common/scaler.h	17 Feb 2005 22:38:40 -0000
@@ -41,6 +41,7 @@
 DECLARE_SCALER(Normal1x);
 DECLARE_SCALER(Normal2x);
 DECLARE_SCALER(Normal3x);
+DECLARE_SCALER(Normal1o5x);
 DECLARE_SCALER(TV2x);
 DECLARE_SCALER(DotMatrix);
 DECLARE_SCALER(HQ2x);
Index: common/system.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/common/system.h,v
retrieving revision 1.86
diff -u -r1.86 system.h
--- common/system.h	11 Jan 2005 13:25:00 -0000	1.86
+++ common/system.h	17 Feb 2005 22:38:59 -0000
@@ -96,7 +96,15 @@
 		 * Implementing this is purely optional, and no harm should arise 
 		 * when not doing so (except for decreased speed in said frontends).
 		 */
-		kFeatureAutoComputeDirtyRects
+		kFeatureAutoComputeDirtyRects,
+
+		/**
+		 * This flags determines either cursor can have its own palette or not
+		 * It is currently used only by some Macintosh versions of Humongous
+		 * Entertainment games. If backend doesn't implement this feature then
+		 * engine switches to b/w version of cursors.
+		 */
+		kFeatureCursorHasPalette
 	};
 	
 	/**
@@ -274,6 +282,18 @@
 	virtual void setPalette(const byte *colors, uint start, uint num) = 0;
 
 	/**
+	 * Replace the specified range of cursor the palette with new colors.
+	 * The palette entries from 'start' till (start+num-1) will be replaced - so
+	 * a full palette update is accomplished via start=0, num=256.
+	 *
+	 * Backends which implement it should have kFeatureCursorHasPalette flag set
+	 *
+	 * @see setPalette
+	 * @see kFeatureCursorHasPalette
+	 */
+	virtual void setCursorPalette(const byte *colors, uint start, uint num) {};
+
+	/**
 	 * Blit a bitmap to the virtual screen.
 	 * The real screen will not immediately be updated to reflect the changes.
 	 * Client code has to to call updateScreen to ensure any changes are
@@ -365,14 +385,15 @@
 	/**
 	 * Set the bitmap used for drawing the cursor.
 	 *
-	 * @param buf		the pixmap data to be used (8bit/pixel)
-	 * @param w			width of the mouse cursor
-	 * @param h			height of the mouse cursor
-	 * @param hotspotX	horizontal offset from the left side to the hotspot
-	 * @param hotspotY	vertical offset from the top side to the hotspot
-	 * @param keycolor	transparency color index
+	 * @param buf				the pixmap data to be used (8bit/pixel)
+	 * @param w					width of the mouse cursor
+	 * @param h					height of the mouse cursor
+	 * @param hotspotX			horizontal offset from the left side to the hotspot
+	 * @param hotspotY			vertical offset from the top side to the hotspot
+	 * @param keycolor			transparency color index
+	 * @param cursorTargetScale	scale factor which cursor is designed for
 	 */
-	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255) = 0;
+	virtual void setMouseCursor(const byte *buf, uint w, uint h, int hotspotX, int hotspotY, byte keycolor = 255, int cursorTargetScale = 1) = 0;
 
 	//@}
 
Index: scumm/cursor.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/cursor.cpp,v
retrieving revision 2.27
diff -u -r2.27 cursor.cpp
--- scumm/cursor.cpp	31 Jan 2005 03:53:35 -0000	2.27
+++ scumm/cursor.cpp	17 Feb 2005 22:38:59 -0000
@@ -107,7 +107,8 @@
 
 void ScummEngine::updateCursor() {
 	_system->setMouseCursor(_grabbedCursor, _cursor.width, _cursor.height,
-							_cursor.hotspotX, _cursor.hotspotY);
+							_cursor.hotspotX, _cursor.hotspotY, 255, 
+							(_heversion == 70 ? 2 : 1));
 }
 
 void ScummEngine_v6::grabCursor(int x, int y, int w, int h) {
Index: scumm/resource_v7he.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/resource_v7he.cpp,v
retrieving revision 1.19
diff -u -r1.19 resource_v7he.cpp
--- scumm/resource_v7he.cpp	11 Feb 2005 03:45:10 -0000	1.19
+++ scumm/resource_v7he.cpp	17 Feb 2005 22:39:11 -0000
@@ -1532,10 +1532,9 @@
 	*hotspot_x = dis.readUint16BE();
 	*w = *h = 16;
 
-	// FIXME
-	// Color cursors use their own palette.
-	// So we can't use it for now and use B/W version
-	return;
+	// Use b/w cursor on backends which don't support cursor palettes
+	if (!_vm->_system->hasFeature(OSystem::kFeatureCursorHasPalette))
+		return;
 
 	dis.readUint32BE(); // reserved
 	dis.readUint32BE(); // cursorID
@@ -1600,12 +1599,7 @@
 		palette[c * 4 + 3] = 0;
 	}
 
-	// TODO: Here we should set separate cursor palette.
-	// It requires cursor to be rendered on a different surface at
-	// least in SDL backend.
-	// HACK: now set global palett just to see if colors are correct.
-	// this affects subtitles colors
-	_vm->_system->setPalette(palette, 0, ctSize);
+	_vm->_system->setCursorPalette(palette, 0, ctSize);
 
 	numBytes =
          (iconBounds[2] - iconBounds[0]) *
