Index: openttd-1.0.2/src/video/sdl_v.cpp
===================================================================
--- openttd-1.0.2.orig/src/video/sdl_v.cpp	2010-06-28 22:59:49.000000000 +0200
+++ openttd-1.0.2/src/video/sdl_v.cpp	2010-06-28 22:59:53.000000000 +0200
@@ -44,9 +44,61 @@
 static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS];
 static int _num_dirty_rects;
 
+static bool _scaled = false;
+static SDL_Surface *_sdl_real_screen;
+
+#ifdef MAEMO
+enum {
+	SCALED_WIND_RES = 0,
+	SCALED_FULL_RES = 1,
+	NATIVE_WIND_RES = 2,
+	NATIVE_FULL_RES = 3
+};
+#endif
+
+static void scaler()
+{
+	const int h = _sdl_screen->h;
+	const int w = _sdl_screen->w;
+	const int src_pitch = _sdl_screen->pitch;
+	const int dst_pitch = _sdl_real_screen->pitch;
+	int x, y;
+	unsigned char *src, *dst;
+
+	src = reinterpret_cast<unsigned char *>(_sdl_screen->pixels);
+	dst = reinterpret_cast<unsigned char *>(_sdl_real_screen->pixels);
+
+	for (y = 0; y < h*2; y++) {
+		for (x = 0; x < w*2; x+=2) {
+			dst[x] = src[x/2];
+			dst[x + 1] = src[x/2];
+		}
+		dst += dst_pitch;
+		if (y&1) src += src_pitch;
+	}
+
+	SDL_CALL SDL_Flip(_sdl_real_screen);
+}
+
+static inline bool compareResolution(const Dimension& d, uint w, uint h)
+{
+	return d.width == w && d.height == h;
+};
+
+static inline bool operator==(const Dimension& d1, const Dimension& d2)
+{
+	return d1.width == d2.width && d1.height == d2.height;
+};
+
+static inline void setToResolution(const Dimension& d, uint* w, uint* h)
+{
+	*w = d.width;
+	*h = d.height;
+};
+
 void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height)
 {
-	if (_num_dirty_rects < MAX_DIRTY_RECTS) {
+	if (!_scaled && _num_dirty_rects < MAX_DIRTY_RECTS) {
 		_dirty_rects[_num_dirty_rects].x = left;
 		_dirty_rects[_num_dirty_rects].y = top;
 		_dirty_rects[_num_dirty_rects].w = width;
@@ -67,6 +119,7 @@
 	}
 
 	SDL_CALL SDL_SetColors(_sdl_screen, pal, _local_palette.first_dirty, _local_palette.count_dirty);
+	if (_scaled) SDL_CALL SDL_SetColors(_sdl_real_screen, pal, _local_palette.first_dirty, _local_palette.count_dirty);
 }
 
 static void InitPalette()
@@ -104,7 +157,9 @@
 	if (n == 0) return;
 
 	_num_dirty_rects = 0;
-	if (n > MAX_DIRTY_RECTS) {
+	if (_scaled) {
+		scaler();
+	} else if (n > MAX_DIRTY_RECTS) {
 		SDL_CALL SDL_UpdateRect(_sdl_screen, 0, 0, 0, 0);
 	} else {
 		SDL_CALL SDL_UpdateRects(_sdl_screen, n, _dirty_rects);
@@ -149,6 +204,39 @@
 	SDL_Rect **modes = SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE | SDL_FULLSCREEN);
 	if (modes == NULL) usererror("sdl: no modes available");
 
+#ifdef MAEMO
+	/* Maemo has only 4 avalaible resolutions:
+	 * * Native windowed + native fullscreen
+	 * * Scaled 2X windowed + scaled fullscreen
+	 */
+	_num_resolutions = 4;
+
+	/* Get fullscreen resolution from SDL */
+	if (!modes[0]) usererror("sdl: no modes available");
+	_resolutions[NATIVE_FULL_RES].width = modes[0]->w;
+	_resolutions[NATIVE_FULL_RES].height = modes[0]->h;
+
+	/* Get scaled fullscreen resolution */
+	_resolutions[SCALED_FULL_RES].width = modes[0]->w / 2;
+	_resolutions[SCALED_FULL_RES].height = modes[0]->h / 2;
+
+	/* Guess windowed native size */
+#if MAEMO_VERSION >= 5
+	/* Fremantle window width */
+	_resolutions[NATIVE_WIND_RES].width = _resolutions[NATIVE_FULL_RES].width;
+#else
+	/* Diablo window width */
+	_resolutions[NATIVE_WIND_RES].width =
+		_resolutions[NATIVE_FULL_RES].width - 80; /* task navigator */
+#endif
+	/* Window height */
+	_resolutions[NATIVE_WIND_RES].height =
+		_resolutions[NATIVE_FULL_RES].height - 60; /* status bar */
+
+	/* Scaled windowed resolution */
+	_resolutions[SCALED_WIND_RES].width = _resolutions[NATIVE_WIND_RES].width / 2;
+	_resolutions[SCALED_WIND_RES].height = _resolutions[NATIVE_WIND_RES].height / 2;
+#else /* MAEMO */
 	_all_modes = (SDL_CALL SDL_ListModes(NULL, SDL_SWSURFACE | (_fullscreen ? SDL_FULLSCREEN : 0)) == (void*)-1);
 	if (modes == (void*)-1) {
 		int n = 0;
@@ -178,8 +266,10 @@
 		_num_resolutions = n;
 		SortResolutions(_num_resolutions);
 	}
+#endif /* MAEMO */
 }
 
+#if !MAEMO
 static void GetAvailableVideoMode(uint *w, uint *h)
 {
 	/* All modes available? */
@@ -203,6 +293,7 @@
 	*w = _resolutions[best].width;
 	*h = _resolutions[best].height;
 }
+#endif /* !MAEMO */
 
 #ifndef ICON_DIR
 #define ICON_DIR "media"
@@ -221,7 +312,25 @@
 	char caption[50];
 	int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 
+#if MAEMO
+	/* Few resolutions available in Maemo */
+	if (compareResolution(_resolutions[NATIVE_FULL_RES], w, h) ||
+		compareResolution(_resolutions[SCALED_FULL_RES], w, h)) {
+		_fullscreen = true;
+		_scaled = compareResolution(_resolutions[SCALED_FULL_RES], w, h);
+	} else if (compareResolution(_resolutions[NATIVE_WIND_RES], w, h) ||
+		compareResolution(_resolutions[SCALED_WIND_RES], w, h)) {
+		_fullscreen = false;
+		_scaled = compareResolution(_resolutions[SCALED_WIND_RES], w, h);
+	} else {
+		// Switch to a default resolution
+		setToResolution(_resolutions[NATIVE_WIND_RES], &w, &h);
+		_fullscreen = false;
+		_scaled = false;
+	}
+#else
 	GetAvailableVideoMode(&w, &h);
+#endif
 
 	DEBUG(driver, 1, "SDL: using mode %ux%ux%d", w, h, bpp);
 
@@ -238,8 +347,17 @@
 		SDL_CALL SDL_FreeSurface(icon);
 	}
 
-	/* DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK */
-	newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
+	if (_scaled) {
+		SDL_FreeSurface(_sdl_screen);
+	}
+	_scaled = compareResolution(_resolutions[SCALED_FULL_RES], w, h) ||
+				compareResolution(_resolutions[SCALED_WIND_RES], w, h);
+	if (_scaled) {
+		_sdl_real_screen = SDL_CALL SDL_SetVideoMode(w*2, h*2, bpp, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : 0));
+		newscreen = SDL_CALL SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, bpp, 0, 0, 0, 0);
+	} else {
+		newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : 0));
+	}
 	if (newscreen == NULL) {
 		DEBUG(driver, 0, "SDL: Couldn't allocate a window to draw on");
 		return false;
@@ -375,6 +493,10 @@
 
 	switch (ev.type) {
 		case SDL_MOUSEMOTION:
+			if (_scaled) {
+				ev.motion.x /= 2;
+				ev.motion.y /= 2;
+			}
 			if (_cursor.fix_at) {
 				int dx = ev.motion.x - _cursor.pos.x;
 				int dy = ev.motion.y - _cursor.pos.y;
@@ -453,13 +575,16 @@
 				HandleKeypress(ConvertSdlKeyIntoMy(&ev.key.keysym));
 			}
 			break;
-
+#ifndef MAEMO
+/* We disable main window resizing in Maemo for obvious reasons. */
+/* Also, workarounds an issue with an eternal resize loop. */
 		case SDL_VIDEORESIZE: {
 			int w = max(ev.resize.w, 64);
 			int h = max(ev.resize.h, 64);
 			CreateMainSurface(w, h);
 			break;
 		}
+#endif /* !MAEMO */
 		case SDL_VIDEOEXPOSE: {
 			/* Force a redraw of the entire screen. Note
 			 * that SDL 1.2 seems to do this automatically
@@ -629,12 +754,26 @@
 bool VideoDriver_SDL::ToggleFullscreen(bool fullscreen)
 {
 	_fullscreen = fullscreen;
+#if MAEMO
+	if (fullscreen) {
+		if (_cur_resolution == _resolutions[SCALED_WIND_RES])
+			CreateMainSurface(_resolutions[SCALED_FULL_RES].width, _resolutions[SCALED_FULL_RES].height);
+		else
+			CreateMainSurface(_resolutions[NATIVE_FULL_RES].width, _resolutions[NATIVE_FULL_RES].height);
+	} else {
+		if (_cur_resolution == _resolutions[SCALED_FULL_RES])
+			CreateMainSurface(_resolutions[SCALED_WIND_RES].width, _resolutions[SCALED_WIND_RES].height);
+		else
+			CreateMainSurface(_resolutions[NATIVE_WIND_RES].width, _resolutions[NATIVE_WIND_RES].height);
+	}
+#else
 	GetVideoModes(); // get the list of available video modes
 	if (_num_resolutions == 0 || !CreateMainSurface(_cur_resolution.width, _cur_resolution.height)) {
 		/* switching resolution failed, put back full_screen to original status */
 		_fullscreen ^= true;
 		return false;
 	}
+#endif /* MAEMO */
 	return true;
 }
 
Index: openttd-1.0.2/src/strings.cpp
===================================================================
--- openttd-1.0.2.orig/src/strings.cpp	2010-06-04 23:07:08.000000000 +0200
+++ openttd-1.0.2/src/strings.cpp	2010-06-28 22:59:53.000000000 +0200
@@ -1240,9 +1240,20 @@
 	/* resolution size? */
 	if (IsInsideMM(ind, (SPECSTR_RESOLUTION_START - 0x70E4), (SPECSTR_RESOLUTION_END - 0x70E4) + 1)) {
 		int i = ind - (SPECSTR_RESOLUTION_START - 0x70E4);
+#if MAEMO
+#define	SCALED_WIND_RES 0
+#define	SCALED_FULL_RES 1
+#define	NATIVE_WIND_RES 2
+#define	NATIVE_FULL_RES 3
+		buff += seprintf(
+			buff, last, "%ux%u %s", _resolutions[i].width, _resolutions[i].height,
+			i == SCALED_FULL_RES || i == NATIVE_FULL_RES ? GetStringPtr(STR_GAME_OPTIONS_FULLSCREEN) : ""
+		);
+#else
 		buff += seprintf(
 			buff, last, "%ux%u", _resolutions[i].width, _resolutions[i].height
 		);
+#endif /* MAEMO */
 		return buff;
 	}
 
