Index: backends/sdl/events.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/events.cpp,v
retrieving revision 1.7
diff -u -r1.7 events.cpp
--- backends/sdl/events.cpp	31 Jul 2004 11:32:25 -0000	1.7
+++ backends/sdl/events.cpp	23 Aug 2004 00:04:48 -0000
@@ -79,8 +79,13 @@
 	km.y = y;
 
 	// Adjust for the screen scaling
-	event.mouse.x /= _scaleFactor;
-	event.mouse.y /= _scaleFactor;
+	if (!_overlayVisible) {
+		event.mouse.x /= _scaleFactor;
+		event.mouse.y /= _scaleFactor;
+	} else {
+		event.mouse.x = event.mouse.x * _scaleFactor / _overlayScale;
+		event.mouse.y = event.mouse.y * _scaleFactor / _overlayScale;
+	}
 
 	// Optionally perform aspect ratio adjusting
 	if (_adjustAspectRatio)
@@ -300,7 +305,8 @@
 				if (ev.key.keysym.sym == SDLK_EQUALS || ev.key.keysym.sym == SDLK_PLUS || ev.key.keysym.sym == SDLK_MINUS ||
 					ev.key.keysym.sym == SDLK_KP_PLUS || ev.key.keysym.sym == SDLK_KP_MINUS) {
 					factor += (ev.key.keysym.sym == SDLK_MINUS || ev.key.keysym.sym == SDLK_KP_MINUS) ? -1 : +1;
-					if (0 <= factor && factor < 4 && s_gfxModeSwitchTable[_scalerType][factor] >= 0) {
+					if (0 <= factor && factor < 4 && s_gfxModeSwitchTable[_scalerType][factor] >= 0 
+							&& factor >= _overlayScale-1) {
 						newMode = s_gfxModeSwitchTable[_scalerType][factor];
 					}
 				}
Index: backends/sdl/graphics.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/graphics.cpp,v
retrieving revision 1.11
diff -u -r1.11 graphics.cpp
--- backends/sdl/graphics.cpp	16 Jul 2004 09:29:09 -0000	1.11
+++ backends/sdl/graphics.cpp	23 Aug 2004 00:05:07 -0000
@@ -41,6 +41,14 @@
 	{0, 0, 0}
 };
 
+// Scalers used for overlay scaler
+// [_overlayScale-1][_scaleFactor-1]
+static ScalerProc *overlayScalers[3][3] = {
+	{ Normal1x, Normal2x, Normal3x }, // [1] 1 2 3
+	{ 0, Normal1x, Normal1o5x },      // [2] 1 2 3
+	{ 0, 0, Normal1x }
+};
+
 const OSystem::GraphicsMode *OSystem_SDL::getSupportedGraphicsModes() const {
 	return s_supportedGraphicsModes;
 }
@@ -135,9 +143,9 @@
 	return _mode;
 }
 
-void OSystem_SDL::initSize(uint w, uint h) {
+void OSystem_SDL::initSize(uint w, uint h, uint overlayScale) {
 	// Avoid redundant res changes
-	if ((int)w == _screenWidth && (int)h == _screenHeight)
+	if ((int)w == _screenWidth && (int)h == _screenHeight && (int)overlayScale == _overlayScale)
 		return;
 
 	_screenWidth = w;
@@ -146,6 +154,13 @@
 	if (h != 200)
 		_adjustAspectRatio = false;
 
+	_overlayScale = overlayScale;
+	if (w != 320)
+		_overlayScale = 1;
+
+	_overlayWidth = w * _overlayScale;
+	_overlayHeight = h * _overlayScale;
+
 	CKSUM_NUM = (_screenWidth * _screenHeight / (8 * 8));
 
 	free(_dirty_checksums);
@@ -155,20 +170,21 @@
 
 	unload_gfx_mode();
 	load_gfx_mode();
+
+	// if initSize() gets called in the middle, overlay is not transparent
+	clearOverlay();
 }
 
 void OSystem_SDL::load_gfx_mode() {
 	_forceFull = true;
 	_mode_flags |= DF_UPDATE_EXPAND_1_PIXEL;
-
-	_tmpscreen = NULL;
 	
 	//
 	// Create the surface that contains the 8 bit game data
 	//
 	_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth, _screenHeight, 8, 0, 0, 0, 0);
 	if (_screen == NULL)
-		error("allocating _screen failed");
+		error("allocating _screen failed: %s", SDL_GetError());
 
 	//
 	// Create the surface that contains the scaled graphics in 16 bit mode
@@ -209,18 +225,40 @@
 		InitScalers(565);
 	
 	// Need some extra bytes around when using 2xSaI
-	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE,
-						_screenWidth + 3,
-						_screenHeight + 3,
+	_tmpscreen = SDL_CreateRGBSurface(SDL_SWSURFACE, _screenWidth + 3, _screenHeight + 3, 16, 0, 0, 0, 0);
+
+	if (_tmpscreen == NULL)
+		error("allocating _tmpscreen failed");
+
+	_overlayscreen = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_overlayWidth,
+						_overlayHeight,
 						16,
 						_hwscreen->format->Rmask,
 						_hwscreen->format->Gmask,
 						_hwscreen->format->Bmask,
 						_hwscreen->format->Amask);
 
-	if (_tmpscreen == NULL)
-		error("allocating _tmpscreen failed");
-	
+	if (_overlayscreen == NULL)
+		error("allocating _overlayscreen failed");
+	SDL_SetColorKey(_overlayscreen, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOverlayColorKey);
+
+	int tmpheight = _overlayHeight * _scaleFactor / _overlayScale;
+	if (_adjustAspectRatio)
+		tmpheight = real2Aspect(tmpheight);
+	_tmpscreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
+						_overlayWidth * _scaleFactor / _overlayScale,
+						tmpheight,
+						16,
+						_hwscreen->format->Rmask,
+						_hwscreen->format->Gmask,
+						_hwscreen->format->Bmask,
+						_hwscreen->format->Amask);
+
+	if (_tmpscreen2 == NULL)
+		error("allocating _tmpscreen2 failed");
+	SDL_SetColorKey(_tmpscreen2, SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA, kOverlayColorKey);
+
 #ifdef USE_OSD
 	_osdSurface = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_RLEACCEL | SDL_SRCCOLORKEY | SDL_SRCALPHA,
 						_hwscreen->w,
@@ -258,6 +296,16 @@
 		_tmpscreen = NULL;
 	}
 
+	if (_tmpscreen2) {
+		SDL_FreeSurface(_tmpscreen2);
+		_tmpscreen2 = NULL;
+	}
+
+	if (_overlayscreen) {
+		SDL_FreeSurface(_overlayscreen);
+		_overlayscreen = NULL;
+	}
+
 #ifdef USE_OSD
 	if (_osdSurface) {
 		SDL_FreeSurface(_osdSurface);
@@ -270,14 +318,17 @@
 	if (!_screen)
 		return;
 
-	// Keep around the old _screen & _tmpscreen so we can restore the screen data
+	// Keep around the old _screen & _overlayscreen so we can restore the screen data
 	// after the mode switch.
 	SDL_Surface *old_screen = _screen;
-	SDL_Surface *old_tmpscreen = _tmpscreen;
+	SDL_Surface *old_overlayscreen = _overlayscreen;
 
 	// Release the HW screen surface
 	SDL_FreeSurface(_hwscreen); 
 
+	SDL_FreeSurface(_tmpscreen); 
+	SDL_FreeSurface(_tmpscreen2); 
+
 #ifdef USE_OSD
 	// Release the OSD surface
 	SDL_FreeSurface(_osdSurface); 
@@ -291,11 +342,18 @@
 
 	// Restore old screen content
 	SDL_BlitSurface(old_screen, NULL, _screen, NULL);
-	SDL_BlitSurface(old_tmpscreen, NULL, _tmpscreen, NULL);
+
+	// FIXME: for some reason simple blit doesn't keep keycolor transparency
+	SDL_LockSurface(_overlayscreen);
+	SDL_LockSurface(old_overlayscreen);
+	Normal1x((byte *)old_overlayscreen->pixels, old_overlayscreen->pitch,
+						(byte *)_overlayscreen->pixels, _overlayscreen->pitch, _overlayWidth, _overlayHeight);
+	SDL_UnlockSurface(_overlayscreen);
+	SDL_UnlockSurface(old_overlayscreen);
 	
 	// Free the old surfaces
 	SDL_FreeSurface(old_screen);
-	SDL_FreeSurface(old_tmpscreen);
+	SDL_FreeSurface(old_overlayscreen);
 
 	// Blit everything to the screen
 	internUpdateScreen();
@@ -380,29 +438,23 @@
 		uint32 srcPitch, dstPitch;
 		SDL_Rect *last_rect = _dirty_rect_list + _num_dirty_rects;
 
-		if (_scaler_proc == Normal1x && !_adjustAspectRatio) {
-			SDL_Surface *target = _overlayVisible ? _tmpscreen : _screen;
+		if (_scaler_proc == Normal1x && !_adjustAspectRatio && 0) {
 			for (r = _dirty_rect_list; r != last_rect; ++r) {
 				dst = *r;
 				
-				if (_overlayVisible) {
-					// FIXME: I don't understand why this is necessary...
-					dst.x--;
-					dst.y--;
-				}
 				dst.y += _currentShakePos;
-				if (SDL_BlitSurface(target, r, _hwscreen, &dst) != 0)
+				if (SDL_BlitSurface(_screen, r, _hwscreen, &dst) != 0)
 					error("SDL_BlitSurface failed: %s", SDL_GetError());
 			}
+			if (SDL_BlitSurface(_overlayscreen, 0, _hwscreen, 0) != 0)
+				error("SDL_BlitSurface failed: %s", SDL_GetError());
 		} else {
-			if (!_overlayVisible) {
-				for (r = _dirty_rect_list; r != last_rect; ++r) {
-					dst = *r;
-					dst.x++;	// Shift rect by one since 2xSai needs to acces the data around
-					dst.y++;	// any pixel to scale it, and we want to avoid mem access crashes.
-					if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
-						error("SDL_BlitSurface failed: %s", SDL_GetError());
-				}
+			for (r = _dirty_rect_list; r != last_rect; ++r) {
+				dst = *r;
+				dst.x++;	// Shift rect by one since 2xSai needs to acces the data around
+				dst.y++;	// any pixel to scale it, and we want to avoid mem access crashes.
+				if (SDL_BlitSurface(_screen, r, _tmpscreen, &dst) != 0)
+					error("SDL_BlitSurface failed: %s", SDL_GetError());
 			}
 
 			SDL_LockSurface(_tmpscreen);
@@ -439,9 +491,27 @@
 
 				if (_adjustAspectRatio && orig_dst_y / _scaleFactor < _screenHeight)
 					r->h = stretch200To240((uint8 *) _hwscreen->pixels, dstPitch, r->w, r->h, r->x, r->y, orig_dst_y);
+
 			}
 			SDL_UnlockSurface(_tmpscreen);
 			SDL_UnlockSurface(_hwscreen);
+
+			srcPitch = _overlayscreen->pitch;
+			dstPitch = _tmpscreen2->pitch;
+
+			SDL_LockSurface(_tmpscreen2);
+			SDL_LockSurface(_overlayscreen);
+			(overlayScalers[_overlayScale-1][_scaleFactor-1])((byte *)_overlayscreen->pixels, srcPitch,
+						(byte *)_tmpscreen2->pixels, dstPitch, _overlayWidth, _overlayHeight);
+			if (_adjustAspectRatio)
+				stretch200To240((uint8 *)_tmpscreen2->pixels, _tmpscreen2->pitch, 
+					_overlayWidth * _scaleFactor / _overlayScale, _overlayHeight * _scaleFactor / _overlayScale, 
+					0, 0, 0);
+
+			SDL_UnlockSurface(_tmpscreen2);
+			SDL_UnlockSurface(_overlayscreen);
+			if (SDL_BlitSurface(_tmpscreen2, 0, _hwscreen, 0) != 0)
+				error("SDL_BlitSurface failed: %s", SDL_GetError());
 		}
 
 		// Readjust the dirty rect list in case we are doing a full update.
@@ -813,59 +883,69 @@
 	undraw_mouse();
 
 	_overlayVisible = false;
+	clearOverlay();
 	_forceFull = true;
 }
 
 void OSystem_SDL::clearOverlay() {
-	if (!_overlayVisible)
-		return;
-	
 	Common::StackLock lock(_graphicsMutex);	// Lock the mutex until this function ends
 	
 	// hide the mouse
 	undraw_mouse();
 
-	// 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 = _screenWidth;
-	src.h = dst.h = _screenHeight;
-	if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
-		error("SDL_BlitSurface failed: %s", SDL_GetError());
-
+	if (!_overlayVisible) {
+		// Fill everything with the "transparent" color, i.e. the colorkey
+		SDL_FillRect(_overlayscreen, 0, kOverlayColorKey);
+	} else {
+		// 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 = _screenWidth;
+		src.h = dst.h = _screenHeight;
+		if (SDL_BlitSurface(_screen, &src, _tmpscreen, &dst) != 0)
+			error("SDL_BlitSurface failed: %s", SDL_GetError());
+
+		SDL_LockSurface(_tmpscreen);
+		SDL_LockSurface(_overlayscreen);
+		if (_overlayScale == _scaleFactor) {
+			_scaler_proc((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, 
+				_tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
+		} else {
+			// Quality is degraded here. It is possible to run one-less scaler here, but is it
+			// really needed? Quality will anyway be degraded because of 1.5x scaler.
+			(overlayScalers[0][_overlayScale-1])((byte *)(_tmpscreen->pixels) + _tmpscreen->pitch + 2, 
+				_tmpscreen->pitch, (byte *)_overlayscreen->pixels, _overlayscreen->pitch, _screenWidth, _screenHeight);
+		}
+		SDL_UnlockSurface(_tmpscreen);
+		SDL_UnlockSurface(_overlayscreen);
+	}
 	_forceFull = true;
 }
 
 void OSystem_SDL::grabOverlay(OverlayColor *buf, int pitch) {
-	if (!_overlayVisible)
-		return;
-
-	if (_tmpscreen == NULL)
+	if (_overlayscreen == NULL)
 		return;
 
 	// hide the mouse
 	undraw_mouse();
 
-	if (SDL_LockSurface(_tmpscreen) == -1)
+	if (SDL_LockSurface(_overlayscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
-	byte *src = (byte *)_tmpscreen->pixels + _tmpscreen->pitch + 2;	// Offset by one row, one column
-	int h = _screenHeight;
+	byte *src = (byte *)_overlayscreen->pixels;
+	int h = _overlayHeight;
 	do {
-		memcpy(buf, src, _screenWidth*2);
-		src += _tmpscreen->pitch;
+		memcpy(buf, src, _overlayWidth*2);
+		src += _overlayscreen->pitch;
 		buf += pitch;
 	} while (--h);
 
-	SDL_UnlockSurface(_tmpscreen);
+	SDL_UnlockSurface(_overlayscreen);
 }
 
 void OSystem_SDL::copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) {
-	if (!_overlayVisible)
-		return;
-
-	if (_tmpscreen == NULL)
+	if (_overlayscreen == NULL)
 		return;
 
 	// Clip the coordinates
@@ -880,12 +960,12 @@
 		y = 0;
 	}
 
-	if (w > _screenWidth - x) {
-		w = _screenWidth - x;
+	if (w > _overlayWidth - x) {
+		w = _overlayWidth - x;
 	}
 
-	if (h > _screenHeight-y) {
-		h = _screenHeight - y;
+	if (h > _overlayHeight-y) {
+		h = _overlayHeight - y;
 	}
 
 	if (w <= 0 || h <= 0)
@@ -893,30 +973,30 @@
 
 	// Mark the modified region as dirty
 	cksum_valid = false;
-	add_dirty_rect(x, y, w, h);
+	add_dirty_rect(OverlayToScreen(x), OverlayToScreen(y), OverlayToScreen(w), OverlayToScreen(h));
 
 	/* FIXME: undraw mouse only if the draw rect intersects with the mouse rect */
 	undraw_mouse();
 
-	if (SDL_LockSurface(_tmpscreen) == -1)
+	if (SDL_LockSurface(_overlayscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
-	byte *dst = (byte *)_tmpscreen->pixels + (y + 1) * _tmpscreen->pitch + (x + 1) * 2;
+	byte *dst = (byte *)_overlayscreen->pixels + y * _overlayscreen->pitch + x * 2;
 	do {
 		memcpy(dst, buf, w * 2);
-		dst += _tmpscreen->pitch;
+		dst += _overlayscreen->pitch;
 		buf += pitch;
 	} while (--h);
 
-	SDL_UnlockSurface(_tmpscreen);
+	SDL_UnlockSurface(_overlayscreen);
 }
 
 OverlayColor OSystem_SDL::RGBToColor(uint8 r, uint8 g, uint8 b) {
-	return SDL_MapRGB(_tmpscreen->format, r, g, b);
+	return SDL_MapRGB(_overlayscreen->format, r, g, b);
 }
 
 void OSystem_SDL::colorToRGB(OverlayColor color, uint8 &r, uint8 &g, uint8 &b) {
-	SDL_GetRGB(color, _tmpscreen->format, &r, &g, &b);
+	SDL_GetRGB(color, _overlayscreen->format, &r, &g, &b);
 }
 
 
@@ -950,7 +1030,10 @@
 
 void OSystem_SDL::warpMouse(int x, int y) {
 	if (_mouseCurState.x != x || _mouseCurState.y != y) {
-		SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
+		if (_overlayVisible)
+			SDL_WarpMouse(x * _scaleFactor / _overlayScale, y * _scaleFactor / _overlayScale);
+		else
+			SDL_WarpMouse(x * _scaleFactor, y * _scaleFactor);
 
 		// SDL_WarpMouse() generates a mouse movement event, so
 		// set_mouse_pos() would be called eventually. However, the
@@ -964,24 +1047,50 @@
 }
 	
 void OSystem_SDL::setMouseCursor(const byte *buf, uint w, uint h, int hotspot_x, int hotspot_y, byte keycolor) {
+	int cursorScale = _overlayScale;
+	int dstPitch;
+	byte *tmpPtr, *dstPtr;
+	const byte *srcPtr = buf;
 
 	undraw_mouse();
 
+	if (!_cursorScaled)
+		cursorScale = 1;
+
 	assert(w <= MAX_MOUSE_W);
 	assert(h <= MAX_MOUSE_H);
-	_mouseCurState.w = w;
-	_mouseCurState.h = h;
+	_mouseCurState.w = w * cursorScale;
+	_mouseCurState.h = h * cursorScale;
 
-	_mouseHotspotX = hotspot_x;
-	_mouseHotspotY = hotspot_y;
+	_mouseHotspotX = hotspot_x * cursorScale;
+	_mouseHotspotY = hotspot_y * cursorScale;
 
 	_mouseKeycolor = keycolor;
 
 	if (_mouseData)
 		free(_mouseData);
 
-	_mouseData = (byte *)malloc(w * h);
-	memcpy(_mouseData, buf, w * h);
+	dstPtr = _mouseData = (byte *)malloc(w * h * cursorScale * cursorScale);
+
+	if (cursorScale == 1) {
+		memcpy(_mouseData, buf, w * h);
+		return;
+	}
+
+	dstPitch = w * cursorScale;
+	for (uint i = 0; i < h; i++) {
+		for (uint j = 0; j < w; j++) {
+			for (int k = 0; k < cursorScale; k++) {
+				tmpPtr = dstPtr + dstPitch * k;
+				for (int l = 0; l < cursorScale; l++) {
+					*tmpPtr++ = *srcPtr;
+				}
+			}
+			srcPtr++;
+			dstPtr += cursorScale;
+		}
+		dstPtr += dstPitch * (cursorScale - 1);
+	}
 }
 
 void OSystem_SDL::toggleMouseGrab() {
@@ -1002,7 +1111,12 @@
 	byte color;
 	const byte *src = _mouseData;		// Image representing the mouse
 
-	// clip the mouse rect, and addjust the src pointer accordingly
+	if (!_overlayVisible) {
+		x = ScreenToOverlay(x);
+		y = ScreenToOverlay(y);
+	}
+
+	// clip the mouse rect, and adjust the src pointer accordingly
 	if (x < 0) {
 		w += x;
 		src -= x;
@@ -1014,66 +1128,43 @@
 		y = 0;
 	}
 
-	if (w > _screenWidth - x)
-		w = _screenWidth - x;
-	if (h > _screenHeight - y)
-		h = _screenHeight - y;
+	if (w > _overlayWidth - x)
+		w = _overlayWidth - x;
+	if (h > _overlayHeight - y)
+		h = _overlayHeight - 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)
+	if (SDL_LockSurface(_overlayscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
 	// Mark as dirty
-	add_dirty_rect(x, y, w, h);
+	add_dirty_rect(OverlayToScreen(x), OverlayToScreen(y), OverlayToScreen(w), OverlayToScreen(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--;
-			}
-			src += _mouseCurState.w - w;
-			bak += MAX_MOUSE_W - w;
-			dst += _screenWidth - w;
-			h--;
-		}
+	uint16 *bak = (uint16 *)_mouseBackup;	// Surface used to backup the area obscured by the mouse
+	byte *dst;					// Surface we are drawing into
 	
-	} 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--;
-		}
+	dst = (byte *)_overlayscreen->pixels + (y + 1) * _overlayscreen->pitch + (x + 1) * 2;
+	while (h > 0) {
+		int width = w;
+		while (width > 0) {
+			*bak++ = *(uint16 *)dst;
+			color = *src++;
+			if (color != _mouseKeycolor)	// 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 += _overlayscreen->pitch - w * 2;
+		h--;
 	}
 
-	SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
+	SDL_UnlockSurface(_overlayscreen);
 
 	// Finally, set the flag to indicate the mouse has been drawn
 	_mouseDrawn = true;
@@ -1084,7 +1175,7 @@
 		return;
 	_mouseDrawn = false;
 
-	if (SDL_LockSurface(_overlayVisible ? _tmpscreen : _screen) == -1)
+	if (SDL_LockSurface(_overlayscreen) == -1)
 		error("SDL_LockSurface failed: %s", SDL_GetError());
 
 	int old_mouse_x = _mouseCurState.x - _mouseHotspotX;
@@ -1092,6 +1183,11 @@
 	int old_mouse_w = _mouseCurState.w;
 	int old_mouse_h = _mouseCurState.h;
 
+	if (!_overlayVisible) {
+		old_mouse_x = ScreenToOverlay(old_mouse_x);
+		old_mouse_y = ScreenToOverlay(old_mouse_y);
+	}
+
 	// clip the mouse rect, and addjust the src pointer accordingly
 	if (old_mouse_x < 0) {
 		old_mouse_w += old_mouse_x;
@@ -1102,10 +1198,10 @@
 		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;
+	if (old_mouse_w > _overlayWidth - old_mouse_x)
+		old_mouse_w = _overlayWidth - old_mouse_x;
+	if (old_mouse_h > _overlayHeight - old_mouse_y)
+		old_mouse_h = _overlayHeight - old_mouse_y;
 
 	// Quick check to see if anything has to be drawn at all
 	if (old_mouse_w <= 0 || old_mouse_h <= 0)
@@ -1113,34 +1209,20 @@
 
 
 	int x, y;
-	if (!_overlayVisible) {
-		byte *dst, *bak = _mouseBackup;
-
-		// No need to do clipping here, since draw_mouse() 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];
-			}
-		}
+	byte *dst;
+	uint16 *bak = (uint16 *)_mouseBackup;
 	
-	} else {
-
-		byte *dst;
-		uint16 *bak = (uint16 *)_mouseBackup;
-	
-		// No need to do clipping here, since draw_mouse() 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];
-			}
+	// No need to do clipping here, since draw_mouse() did that already
+	dst = (byte *)_overlayscreen->pixels + (old_mouse_y + 1) * _overlayscreen->pitch + (old_mouse_x + 1) * 2;
+	for (y = 0; y < old_mouse_h; ++y, bak += MAX_MOUSE_W, dst += _overlayscreen->pitch) {
+		for (x = 0; x < old_mouse_w; ++x) {
+			*((uint16 *)dst + x) = bak[x];
 		}
 	}
 
-	add_dirty_rect(old_mouse_x, old_mouse_y, old_mouse_w, old_mouse_h);
+	add_dirty_rect(OverlayToScreen(old_mouse_x), OverlayToScreen(old_mouse_y), OverlayToScreen(old_mouse_w), OverlayToScreen(old_mouse_h));
 
-	SDL_UnlockSurface(_overlayVisible ? _tmpscreen : _screen);
+	SDL_UnlockSurface(_overlayscreen);
 }
 
 
Index: backends/sdl/sdl-common.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl-common.h,v
retrieving revision 1.62
diff -u -r1.62 sdl-common.h
--- backends/sdl/sdl-common.h	16 Jul 2004 10:24:29 -0000	1.62
+++ backends/sdl/sdl-common.h	23 Aug 2004 00:05:07 -0000
@@ -43,7 +43,7 @@
 
 	// Set the size of the video bitmap.
 	// Typically, 320x200
-	void initSize(uint w, uint h);
+	void initSize(uint w, uint h, uint overlayScale);
 
 	// Set colors of the palette
 	void setPalette(const byte *colors, uint start, uint num);
@@ -59,6 +59,9 @@
 
 	// Either show or hide the mouse cursor
 	bool showMouse(bool visible);
+
+	// Either scale or not the mouse cursor
+	void setCursorScaled(bool state) { _cursorScaled = state; }
 	
 	// Warp the mouse cursor. Where set_mouse_pos() only informs the
 	// backend of the mouse cursor's current position, this function
@@ -120,6 +123,11 @@
 	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 _overlayHeight; }
+	virtual int16 getOverlayWidth()   { return _overlayWidth; }
+	virtual OverlayColor getOverlayKeyColor() { return kOverlayColorKey; }
+	virtual int ScreenToOverlay(int x) { return x * _overlayScale; }
+	virtual int OverlayToScreen(int x) { return x / _overlayScale; }
 
 	// Methods that convert RGB to/from colors suitable for the overlay.
 	virtual OverlayColor RGBToColor(uint8 r, uint8 g, uint8 b);
@@ -165,9 +173,19 @@
 	SDL_Surface *_screen;
 	int _screenWidth, _screenHeight;
 
-	// temporary screen (for scalers/overlay)
+	// temporary screens (for scalers)
 	SDL_Surface *_tmpscreen;
+	SDL_Surface *_tmpscreen2;
+
+	// overlay
+	SDL_Surface *_overlayscreen;
+	int _overlayWidth, _overlayHeight;
+	int _overlayScale;
 	bool _overlayVisible;
+	
+	enum {
+		kOverlayColorKey = 1
+	};
 
 	// Audio
 	int _samplesPerSec;
@@ -222,6 +240,7 @@
 	// mouse
 	bool _mouseVisible;
 	bool _mouseDrawn;
+	bool _cursorScaled;
 	byte *_mouseData;
 	byte *_mouseBackup;
 	MousePos _mouseCurState;
Index: backends/sdl/sdl.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/backends/sdl/sdl.cpp,v
retrieving revision 1.72
diff -u -r1.72 sdl.cpp
--- backends/sdl/sdl.cpp	16 Jul 2004 10:24:29 -0000	1.72
+++ backends/sdl/sdl.cpp	23 Aug 2004 00:05:07 -0000
@@ -94,11 +94,11 @@
 	_osdSurface(0), _osdAlpha(SDL_ALPHA_TRANSPARENT), _osdFadeStartTime(0),
 #endif
 	_hwscreen(0), _screen(0), _screenWidth(0), _screenHeight(0),
-	_tmpscreen(0), _overlayVisible(false),
-	_samplesPerSec(0),
+	_tmpscreen(0), _overlayscreen(0), _overlayVisible(false),
+	_tmpscreen2(0), _samplesPerSec(0),
 	_cdrom(0), _scaler_proc(0), _modeChanged(false), _dirty_checksums(0),
 	_mouseVisible(false), _mouseDrawn(false), _mouseData(0),
-	_mouseHotspotX(0), _mouseHotspotY(0),
+	_mouseHotspotX(0), _mouseHotspotY(0), _cursorScaled(true),
 	_currentShakePos(0), _newShakePos(0),
 	_paletteDirtyStart(0), _paletteDirtyEnd(0),
 	_graphicsMutex(0) {
Index: base/main.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/base/main.cpp,v
retrieving revision 1.46
diff -u -r1.46 main.cpp
--- base/main.cpp	5 Aug 2004 11:13:00 -0000	1.46
+++ base/main.cpp	23 Aug 2004 00:05:07 -0000
@@ -182,10 +182,10 @@
 
 	// FIXME - we need to call initSize() here so that we can display for example
 	// the launcher dialog. But the Engine object will also call it again (possibly
-	// with a different widht/height!9 However, this method is not for all OSystem 
+	// with a different widht/height! However, this method is not for all OSystem 
 	// implementations reentrant (it is so now for the SDL backend). Thus we need
 	// to fix all backends to support it, if they don't already.
-	system->initSize(320, 200);
+	system->initSize(320, 200, 2);
 	
 	// FIXME - mouse cursors are currently always set via 8 bit data.
 	// Thus for now we need to setup a dummy palette. On the long run, we might
Index: common/scaler.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/common/scaler.cpp,v
retrieving revision 1.63
diff -u -r1.63 scaler.cpp
--- common/scaler.cpp	10 Aug 2004 17:46:04 -0000	1.63
+++ common/scaler.cpp	23 Aug 2004 00:05:07 -0000
@@ -105,7 +105,7 @@
 
 /**
  * Trivial 'scaler' - in fact it doesn't do any scaling but just copies the
- * source to the destionation.
+ * source to the destination.
  */
 void Normal1x(const uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch,
 							int width, int height) {
@@ -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.26
diff -u -r1.26 scaler.h
--- common/scaler.h	21 May 2004 20:43:07 -0000	1.26
+++ common/scaler.h	23 Aug 2004 00:05:07 -0000
@@ -40,6 +40,7 @@
 DECLARE_SCALER(AdvMame3x);
 DECLARE_SCALER(Normal1x);
 DECLARE_SCALER(Normal2x);
+DECLARE_SCALER(Normal1o5x);
 DECLARE_SCALER(Normal3x);
 DECLARE_SCALER(TV2x);
 DECLARE_SCALER(DotMatrix);
Index: common/system.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/common/system.h,v
retrieving revision 1.68
diff -u -r1.68 system.h
--- common/system.h	25 Jun 2004 22:11:47 -0000	1.68
+++ common/system.h	23 Aug 2004 00:05:35 -0000
@@ -216,7 +216,7 @@
 	 * @param width		the new virtual screen width
 	 * @param height	the new virtual screen height
 	 */
-	virtual void initSize(uint width, uint height) = 0;
+	virtual void initSize(uint width, uint height, uint overlayScale = 1) = 0;
 
 	/**
 	 * Returns the currently set virtual screen height.
@@ -305,6 +305,9 @@
 	virtual void copyRectToOverlay(const OverlayColor *buf, int pitch, int x, int y, int w, int h) = 0;
 	virtual int16 getOverlayHeight()  { return getHeight(); }
 	virtual int16 getOverlayWidth()   { return getWidth(); }
+	virtual OverlayColor getOverlayKeyColor() { return RGBToColor(0, 0, 0); }
+	virtual int ScreenToOverlay(int x) { return x; }
+	virtual int OverlayToScreen(int x) { return x; }
 
 	/**
 	* Convert the given RGB triplet into an OverlayColor. A OverlayColor can
@@ -340,6 +343,9 @@
 	/** Show or hide the mouse cursor. */
 	virtual bool showMouse(bool visible) = 0;
 
+	/** Scale cursor with screen scale rate change or not */
+	virtual void setCursorScaled(bool state) { }
+
 	/** 
 	 * Move ("warp") the mouse cursor to the specified position in virtual 
 	 * screen coordinates.
@@ -435,7 +441,7 @@
 		/**
 		 * The mouse coordinates, in virtual screen coordinates. Only valid
 		 * for mouse events.
-		 * Virtual screen coordinatest means: the coordinate system of the
+		 * Virtual screen coordinates mean: the coordinate system of the
 		 * screen area as defined by the most recent call to initSize().
 		 */
 		Common::Point mouse;
Index: doc/he/md5s.txt
===================================================================
RCS file: /cvsroot/scummvm/scummvm/doc/he/md5s.txt,v
retrieving revision 1.7
diff -u -r1.7 md5s.txt
--- doc/he/md5s.txt	1 Jul 2004 21:54:49 -0000	1.7
+++ doc/he/md5s.txt	23 Aug 2004 00:05:55 -0000
@@ -64,7 +64,7 @@
 42161ad979949daf67924b5227b94f2d  airdemo.he4
 765492059d83bc0ae8c30a4feef50a6a  airdemo.he9
 
-(spyfox cd/pjs cd/puttzoo cd/he classics cd)
+(spyfox cd/pjs cd/puttzoo cd/he classics cd/freddi2 cd)
 khalek, sev
 7.0.0 (Jul  5 1995 14:46:05)
 a5459bfe36183cf1f4ced00fe325aa90  airdemo.w32
@@ -275,7 +275,7 @@
 6daf76c1fe724ce6bf2e4c5175f39352  freddemo.he3
 a8c3ced34ecb16ad1b0eed5b464ad61e  freddemo.he4
 
-(spyfox cd/pjs cd/puttzoo cd/he classics cd)
+(spyfox cd/pjs cd/puttzoo cd/he classics cd/freddi2 cd)
 khalek, sev
 7.0.0 (Jul  5 1995 14:46:05)
 25003798cd5f4b51bc1f4d02c6a2e218  freddemo.w32
@@ -344,6 +344,15 @@
 faca7509c38beabb37b2347b8b6bb1ea  Freddi Demo (2)
 a8c3ced34ecb16ad1b0eed5b464ad61e  Freddi Demo (4)
 
+(freddi2 cd)
+sev
+D:\Scummsrc.80\Sputm\*.c
+d06066ae0ba8ffb338d6a00f556ae3ac FREDDI2.W32
+5057fb0e99e5aa29df1836329232f101 FREDDI2.HE0
+a586db95af3146aa7793c5e2d0ed9e83 FREDDI2.HE1
+9ff9a777a343e605278127c0bbdde58f FREDDI2.HE2
+d22f1b3bd41cb4901f89164043953bc8 FREDDI2.HE4
+
 (russian freddi)
 sev
 D:\Scummsrc.80\Sputm\*.c
@@ -573,7 +582,7 @@
 4ccd03ca710a9053c42292cae09a6471  Pajama Sam Demo (2)
 6e0fdfcf13e37b659b7155cf5969965f  Pajama Sam Demo (4)
 
-(spyfox cd/puttzoo cd/he classics cd/pj2 cd)
+(spyfox cd/puttzoo cd/he classics cd/pj2 cd/freddi2 cd)
 khalek, sev
 1996-10-31 22:34 pjs-demo.w32
 D:\Scummsrc.80\Sputm\*.c
@@ -920,7 +929,7 @@
 225991e6f8d3d6ac5e519413392c34f3  Putt-Putt Saves the Zoo (2)
 d3235443d88751acd3412c1b0c6cec35  Putt-Putt Saves the Zoo (4)
 
-(spyfox cd/pjs cd/he classics cd)
+(spyfox cd/pjs cd/he classics cd/freddi2 cd)
 khalek
 7.0.0 (Jun  4 1995 15:47:12)
 f3324cfe3dec0288fd38197cf88962af  zoodemo.w32
Index: scumm/scumm.cpp
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.cpp,v
retrieving revision 1.131
diff -u -r1.131 scumm.cpp
--- scumm/scumm.cpp	22 Aug 2004 08:59:33 -0000	1.131
+++ scumm/scumm.cpp	23 Aug 2004 00:06:52 -0000
@@ -808,7 +808,9 @@
 	}
 
 	// Initialize backend
-	syst->initSize(_screenWidth, _screenHeight);
+	syst->initSize(_screenWidth, _screenHeight, 2);
+	syst->setCursorScaled((_features & GF_UNSCALED_CURSORS) == 0);
+
 	int cd_num = ConfMan.getInt("cdrom");
 	if (cd_num >= 0 && (_features & GF_AUDIOTRACKS))
 		syst->openCD(cd_num);
@@ -3195,7 +3197,7 @@
 		// specify correct version here
 		if (game.features & GF_HUMONGOUS && (game.heversion == 60 || game.id == GID_PUTTDEMO)) {
 			game.heversion = 70;
-			game.features |= GF_NEW_COSTUMES;
+			game.features |= GF_NEW_COSTUMES | GF_UNSCALED_CURSORS;
 		}
 		break;
 	case Common::kPlatformFMTowns:
Index: scumm/scumm.h
===================================================================
RCS file: /cvsroot/scummvm/scummvm/scumm/scumm.h,v
retrieving revision 1.445
diff -u -r1.445 scumm.h
--- scumm/scumm.h	22 Aug 2004 09:38:18 -0000	1.445
+++ scumm/scumm.h	23 Aug 2004 00:07:15 -0000
@@ -113,6 +113,7 @@
 	GF_FEW_LOCALS          = 1 << 13,
 	GF_HUMONGOUS           = 1 << 14,
 	GF_MULTIPLE_VERSIONS   = 1 << 15,
+	GF_UNSCALED_CURSORS    = 1 << 16,
 	
 	GF_FMTOWNS             = 1 << 17,
 	GF_AMIGA               = 1 << 18,
