(svn r10121) -Codechange: split renderer from rest of code; no longer any code directly accesses the video-buffer
authortruelight
Tue, 12 Jun 2007 20:24:12 +0000
changeset 7374 54c06f06ecc8
parent 7373 938b0afa92ed
child 7375 e8639f73a615
(svn r10121) -Codechange: split renderer from rest of code; no longer any code directly accesses the video-buffer
-Add: added NULL blitter and renderer, which are always used for -vnull
-Add: dedicated driver doesn't blit nor render by default. Can be overruled by user. (-D -b 8bpp-optimized)
-Remove: removed CTRL+D from win32, which is incompatible with above
-Add: extended screenshot support for PNG and BMP
-Codechange: remove all hardcoded 8bpp references and replace them with more dynamic ones
-Codechange: minor stuff in blitters
projects/openttd.vcproj
projects/openttd_vs80.vcproj
source.list
src/blitter/8bpp_debug.cpp
src/blitter/8bpp_debug.hpp
src/blitter/8bpp_optimized.cpp
src/blitter/8bpp_optimized.hpp
src/blitter/8bpp_simple.cpp
src/blitter/8bpp_simple.hpp
src/blitter/blitter.hpp
src/blitter/null.cpp
src/blitter/null.hpp
src/gfx.cpp
src/gfx.h
src/openttd.cpp
src/renderer/8bpp.cpp
src/renderer/8bpp.hpp
src/renderer/null.cpp
src/renderer/null.hpp
src/renderer/renderer.hpp
src/screenshot.cpp
src/settings.cpp
src/smallmap_gui.cpp
src/texteff.cpp
src/video/cocoa_v.mm
src/video/dedicated_v.cpp
src/video/null_v.cpp
src/video/sdl_v.cpp
src/video/win32_v.cpp
src/viewport.cpp
src/window.cpp
--- a/projects/openttd.vcproj	Tue Jun 12 18:10:14 2007 +0000
+++ b/projects/openttd.vcproj	Tue Jun 12 20:24:12 2007 +0000
@@ -980,6 +980,12 @@
 				RelativePath=".\..\src\blitter\8bpp_simple.hpp">
 			</File>
 			<File
+				RelativePath=".\..\src\blitter\null.cpp">
+			</File>
+			<File
+				RelativePath=".\..\src\blitter\null.hpp">
+			</File>
+			<File
 				RelativePath=".\..\src\blitter\blitter.hpp">
 			</File>
 		</Filter>
@@ -997,6 +1003,25 @@
 			</File>
 		</Filter>
 		<Filter
+			Name="Renderer"
+			Filter="">
+			<File
+				RelativePath=".\..\src\renderer\8bpp.cpp">
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\8bpp.hpp">
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\null.cpp">
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\null.hpp">
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\renderer.hpp">
+			</File>
+		</Filter>
+		<Filter
 			Name="NewGRF"
 			Filter="">
 			<File
--- a/projects/openttd_vs80.vcproj	Tue Jun 12 18:10:14 2007 +0000
+++ b/projects/openttd_vs80.vcproj	Tue Jun 12 20:24:12 2007 +0000
@@ -1528,6 +1528,14 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\blitter\null.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\blitter\null.hpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\blitter\blitter.hpp"
 				>
 			</File>
@@ -1549,6 +1557,30 @@
 			</File>
 		</Filter>
 		<Filter
+			Name="Renderer"
+			>
+			<File
+				RelativePath=".\..\src\renderer\8bpp.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\8bpp.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\null.cpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\null.hpp"
+				>
+			</File>
+			<File
+				RelativePath=".\..\src\renderer\renderer.hpp"
+				>
+			</File>
+		</Filter>
+		<Filter
 			Name="NewGRF"
 			>
 			<File
--- a/source.list	Tue Jun 12 18:10:14 2007 +0000
+++ b/source.list	Tue Jun 12 20:24:12 2007 +0000
@@ -297,6 +297,8 @@
 blitter/8bpp_optimized.hpp
 blitter/8bpp_simple.cpp
 blitter/8bpp_simple.hpp
+blitter/null.cpp
+blitter/null.hpp
 blitter/blitter.hpp
 
 # Sprite loaders
@@ -304,6 +306,13 @@
 spriteloader/grf.hpp
 spriteloader/spriteloader.hpp
 
+# Renderer
+renderer/8bpp.cpp
+renderer/8bpp.hpp
+renderer/null.cpp
+renderer/null.hpp
+renderer/renderer.hpp
+
 # NewGRF
 newgrf.cpp
 newgrf_canal.cpp
--- a/src/blitter/8bpp_debug.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_debug.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -12,12 +12,12 @@
 
 void Blitter_8bppDebug::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
 {
-	const byte *src, *src_line;
-	Pixel8 *dst, *dst_line;
+	const uint8 *src, *src_line;
+	uint8 *dst, *dst_line;
 
 	/* Find where to start reading in the source sprite */
-	src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
-	dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
+	src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
+	dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
 
 	for (int y = 0; y < bp->height; y++) {
 		dst = dst_line;
--- a/src/blitter/8bpp_debug.hpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_debug.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -7,15 +7,15 @@
 
 #include "blitter.hpp"
 
-typedef Pixel Pixel8;
-
 class Blitter_8bppDebug : public Blitter {
 public:
-	uint8 GetScreenDepth() { return 8; }
+	/* virtual */ uint8 GetScreenDepth() { return 8; }
 
-	void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+	/* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
 
-	Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+	/* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+
+	/* virtual */ const char *GetRenderer() { return "8bpp"; }
 };
 
 class FBlitter_8bppDebug: public BlitterFactory<FBlitter_8bppDebug> {
--- a/src/blitter/8bpp_optimized.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_optimized.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -12,16 +12,16 @@
 
 void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
 {
-	const byte *src, *src_next;
-	Pixel8 *dst, *dst_line;
+	const uint8 *src, *src_next;
+	uint8 *dst, *dst_line;
 	uint offset = 0;
 
 	/* Find the offset of this zoom-level */
-	offset = ((const byte *)bp->sprite)[(int)zoom * 2] | ((const byte *)bp->sprite)[(int)zoom * 2 + 1] << 8;
+	offset = ((const uint8 *)bp->sprite)[(int)zoom * 2] | ((const byte *)bp->sprite)[(int)zoom * 2 + 1] << 8;
 
 	/* Find where to start reading in the source sprite */
-	src = (const byte *)bp->sprite + offset;
-	dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
+	src = (const uint8 *)bp->sprite + offset;
+	dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
 
 	/* Skip over the top lines in the source image */
 	for (int y = 0; y < bp->skip_top; y++) {
--- a/src/blitter/8bpp_optimized.hpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_optimized.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -7,15 +7,15 @@
 
 #include "blitter.hpp"
 
-typedef Pixel Pixel8;
-
 class Blitter_8bppOptimized : public Blitter {
 public:
-	uint8 GetScreenDepth() { return 8; }
+	/* virtual */ uint8 GetScreenDepth() { return 8; }
 
-	void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+	/* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
 
-	Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+	/* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+
+	/* virtual */ const char *GetRenderer() { return "8bpp"; }
 };
 
 class FBlitter_8bppOptimized: public BlitterFactory<FBlitter_8bppOptimized> {
--- a/src/blitter/8bpp_simple.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_simple.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -11,12 +11,12 @@
 
 void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
 {
-	const byte *src, *src_line;
-	Pixel8 *dst, *dst_line;
+	const uint8 *src, *src_line;
+	uint8 *dst, *dst_line;
 
 	/* Find where to start reading in the source sprite */
-	src_line = (const byte *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
-	dst_line = (Pixel8 *)bp->dst + bp->top * bp->pitch + bp->left;
+	src_line = (const uint8 *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
+	dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
 
 	for (int y = 0; y < bp->height; y++) {
 		dst = dst_line;
--- a/src/blitter/8bpp_simple.hpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/8bpp_simple.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -7,15 +7,15 @@
 
 #include "blitter.hpp"
 
-typedef Pixel Pixel8;
-
 class Blitter_8bppSimple : public Blitter {
 public:
-	uint8 GetScreenDepth() { return 8; }
+	/* virtual */ uint8 GetScreenDepth() { return 8; }
 
-	void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+	/* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
 
-	Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+	/* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+
+	/* virtual */ const char *GetRenderer() { return "8bpp"; }
 };
 
 class FBlitter_8bppSimple: public BlitterFactory<FBlitter_8bppSimple> {
--- a/src/blitter/blitter.hpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/blitter/blitter.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -53,6 +53,11 @@
 	 */
 	virtual Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator) = 0;
 
+	/**
+	 * Get the renderer this class depends on.
+	 */
+	virtual const char *GetRenderer() = 0;
+
 	virtual ~Blitter() { }
 };
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/blitter/null.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,24 @@
+#include "../stdafx.h"
+#include "../zoom.hpp"
+#include "../gfx.h"
+#include "../functions.h"
+#include "null.hpp"
+
+static FBlitter_Null iFBlitter_Null;
+
+void Blitter_Null::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
+{
+}
+
+Sprite *Blitter_Null::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
+{
+	Sprite *dest_sprite;
+	dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite));
+
+	dest_sprite->height = sprite->height;
+	dest_sprite->width  = sprite->width;
+	dest_sprite->x_offs = sprite->x_offs;
+	dest_sprite->y_offs = sprite->y_offs;
+
+	return dest_sprite;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/blitter/null.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,30 @@
+/* $Id$ */
+
+/** @file null.hpp */
+
+#ifndef BLITTER_NULL_HPP
+#define BLITTER_NULL_HPP
+
+#include "blitter.hpp"
+
+class Blitter_Null : public Blitter {
+public:
+	/* virtual */ uint8 GetScreenDepth() { return 0; }
+
+	/* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+
+	/* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+
+	/* virtual */ const char *GetRenderer() { return "null"; }
+};
+
+class FBlitter_Null: public BlitterFactory<FBlitter_Null> {
+public:
+	/* virtual */ const char *GetName() { return "null"; }
+
+	/* virtual */ const char *GetDescription() { return "Null Blitter (does nothing)"; }
+
+	/* virtual */ Blitter *CreateInstance() { return new Blitter_Null(); }
+};
+
+#endif /* BLITTER_NULL_HPP */
--- a/src/gfx.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/gfx.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -50,7 +50,7 @@
 
 FontSize _cur_fontsize;
 static FontSize _last_fontsize;
-static Pixel _cursor_backup[64 * 64];
+static uint8 _cursor_backup[64 * 64 * 4];
 static Rect _invalid_rect;
 static const byte *_color_remap_ptr;
 static byte _string_colorremap[3];
@@ -58,37 +58,20 @@
 #define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
 static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
 
-void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch)
-{
-	Pixel *dstp = (Pixel *)dst;
-	Pixel *srcp = (Pixel *)src;
-
-	assert(h >= 0);
-	for (; h != 0; --h) {
-		memcpy(dstp, srcp, w * sizeof(Pixel));
-		dstp += dstpitch;
-		srcp += srcpitch;
-	}
-}
-
 void GfxScroll(int left, int top, int width, int height, int xo, int yo)
 {
-	const Pixel *src;
-	Pixel *dst;
-	int p;
-	int ht;
+	const void *src;
+	void *dst;
 
 	if (xo == 0 && yo == 0) return;
 
 	if (_cursor.visible) UndrawMouseCursor();
 	UndrawTextMessage();
 
-	p = _screen.pitch;
-
 	if (yo > 0) {
 		/*Calculate pointers */
-		dst = _screen.dst_ptr + (top + height - 1) * p + left;
-		src = dst - yo * p;
+		dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top + height - 1);
+		src = _screen.renderer->MoveTo(dst, 0, -yo);
 
 		/* Decrease height and increase top */
 		top += yo;
@@ -97,23 +80,20 @@
 
 		/* Adjust left & width */
 		if (xo >= 0) {
-			dst += xo;
+			dst = _screen.renderer->MoveTo(dst, xo, 0);
 			left += xo;
 			width -= xo;
 		} else {
-			src -= xo;
+			src = _screen.renderer->MoveTo(src, -xo, 0);
 			width += xo;
 		}
 
-		for (ht = height; ht > 0; --ht) {
-			memcpy(dst, src, width * sizeof(Pixel));
-			src -= p;
-			dst -= p;
-		}
+		/* Negative height as we want to copy from bottom to top */
+		_screen.renderer->CopyFromBuffer(dst, src, width, -height, _screen.pitch);
 	} else {
 		/* Calculate pointers */
-		dst = _screen.dst_ptr + top * p + left;
-		src = dst - yo * p;
+		dst = _screen.renderer->MoveTo(_screen.dst_ptr, left, top);
+		src = _screen.renderer->MoveTo(dst, 0, -yo);
 
 		/* Decrese height. (yo is <=0). */
 		height += yo;
@@ -121,21 +101,17 @@
 
 		/* Adjust left & width */
 		if (xo >= 0) {
-			dst += xo;
+			dst = _screen.renderer->MoveTo(dst, xo, 0);
 			left += xo;
 			width -= xo;
 		} else {
-			src -= xo;
+			src = _screen.renderer->MoveTo(src, -xo, 0);
 			width += xo;
 		}
 
 		/* the y-displacement may be 0 therefore we have to use memmove,
 		 * because source and destination may overlap */
-		for (ht = height; ht > 0; --ht) {
-			memmove(dst, src, width * sizeof(Pixel));
-			src += p;
-			dst += p;
-		}
+		_screen.renderer->MoveBuffer(dst, src, width, height);
 	}
 	/* This part of the screen is now dirty. */
 	_video_driver->make_dirty(left, top, width, height);
@@ -144,8 +120,8 @@
 
 void GfxFillRect(int left, int top, int right, int bottom, int color)
 {
-	const DrawPixelInfo* dpi = _cur_dpi;
-	Pixel *dst;
+	const DrawPixelInfo *dpi = _cur_dpi;
+	void *dst;
 	const int otop = top;
 	const int oleft = left;
 
@@ -166,40 +142,37 @@
 	bottom -= top;
 	assert(bottom > 0);
 
-	dst = dpi->dst_ptr + top * dpi->pitch + left;
+	dst = _screen.renderer->MoveTo(dpi->dst_ptr, left, top);
 
 	if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
 		if (!HASBIT(color, USE_COLORTABLE)) {
 			do {
-				memset(dst, color, right * sizeof(Pixel));
-				dst += dpi->pitch;
+				_screen.renderer->SetHorizontalLine(dst, right, (uint8)color);
+				dst = _screen.renderer->MoveTo(dst, 0, 1);
 			} while (--bottom);
 		} else {
 			/* use colortable mode */
 			const byte* ctab = GetNonSprite(GB(color, 0, PALETTE_WIDTH)) + 1;
 
 			do {
-				int i;
-				for (i = 0; i != right; i++) dst[i] = ctab[dst[i]];
-				dst += dpi->pitch;
+				for (int i = 0; i != right; i++) _screen.renderer->SetPixel(dst, i, 0, ctab[((uint8 *)dst)[i]]);
+				dst = _screen.renderer->MoveTo(dst, 0, 1);
 			} while (--bottom);
 		}
 	} else {
 		byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
 		do {
-			int i;
-			for (i = (bo ^= 1); i < right; i += 2) dst[i] = (byte)color;
-			dst += dpi->pitch;
+			for (int i = (bo ^= 1); i < right; i += 2) _screen.renderer->SetPixel(dst, i, 0, (uint8)color);
+			dst = _screen.renderer->MoveTo(dst, 0, 1);
 		} while (--bottom > 0);
 	}
 }
 
 static void GfxSetPixel(int x, int y, int color)
 {
-	const DrawPixelInfo* dpi = _cur_dpi;
-	if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top)<0 || y >= dpi->height)
-		return;
-	dpi->dst_ptr[y * dpi->pitch + x] = color;
+	const DrawPixelInfo *dpi = _cur_dpi;
+	if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top) < 0 || y >= dpi->height) return;
+	_screen.renderer->SetPixel(dpi->dst_ptr, x, y, color);
 }
 
 void GfxDrawLine(int x, int y, int x2, int y2, int color)
@@ -817,6 +790,13 @@
 	Colour old_val[38]; // max(38, 28)
 	uint i;
 	uint j;
+	int old_tc = _timer_counter;
+
+	/* We can only update the palette in 8bpp for now */
+	/* TODO -- We need support for other bpps too! */
+	if (BlitterFactoryBase::GetCurrentBlitter() != NULL && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) {
+		_timer_counter = 0;
+	}
 
 	d = &_cur_palette[217];
 	memcpy(old_val, d, c * sizeof(*old_val));
@@ -913,6 +893,8 @@
 		if (_pal_first_dirty > 217) _pal_first_dirty = 217;
 		if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c;
 	}
+
+	if (old_tc != _timer_counter) _timer_counter = old_tc;
 }
 
 
@@ -959,11 +941,7 @@
 {
 	if (_cursor.visible) {
 		_cursor.visible = false;
-		memcpy_pitch(
-			_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
-			_cursor_backup,
-			_cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x, _screen.pitch);
-
+		_screen.renderer->CopyFromBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup, _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x);
 		_video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y);
 	}
 }
@@ -1006,13 +984,10 @@
 	_cursor.draw_pos.y = y;
 	_cursor.draw_size.y = h;
 
-	assert(w * h < (int)sizeof(_cursor_backup));
+	assert(_screen.renderer->BufferSize(w, h) < (int)sizeof(_cursor_backup));
 
 	/* Make backup of stuff below cursor */
-	memcpy_pitch(
-		_cursor_backup,
-		_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
-		_cursor.draw_size.x, _cursor.draw_size.y, _screen.pitch, _cursor.draw_size.x);
+	_screen.renderer->CopyToBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, _cursor.draw_pos.x, _cursor.draw_pos.y), _cursor_backup, _cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x);
 
 	/* Draw cursor on screen */
 	_cur_dpi = &_screen;
@@ -1233,7 +1208,8 @@
 		n->top = 0;
 	}
 
-	n->dst_ptr = o->dst_ptr + left + top * (n->pitch = o->pitch);
+	n->dst_ptr = _screen.renderer->MoveTo(o->dst_ptr, left, top);
+	n->pitch = o->pitch;
 
 	if (height > o->height - top) {
 		height = o->height - top;
--- a/src/gfx.h	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/gfx.h	Tue Jun 12 20:24:12 2007 +0000
@@ -7,6 +7,7 @@
 
 #include "openttd.h"
 #include "zoom.hpp"
+#include "renderer/renderer.hpp"
 
 enum WindowKeyCodes {
 	WKC_SHIFT = 0x8000,
@@ -93,7 +94,6 @@
 void CreateConsole();
 
 typedef int32 CursorID;
-typedef byte Pixel;
 
 struct Point {
 	int x,y;
@@ -134,10 +134,11 @@
 };
 
 struct DrawPixelInfo {
-	Pixel *dst_ptr;
+	void *dst_ptr;
 	int left, top, width, height;
 	int pitch;
 	ZoomLevel zoom;
+	Renderer *renderer;
 };
 
 struct Colour {
--- a/src/openttd.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/openttd.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -402,6 +402,7 @@
 			strcpy(musicdriver, "null");
 			strcpy(sounddriver, "null");
 			strcpy(videodriver, "dedicated");
+			strcpy(blitter, "null");
 			dedicated = true;
 			if (mgo.opt != NULL) {
 				/* Use the existing method for parsing (openttd -n).
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/renderer/8bpp.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,71 @@
+#include "../stdafx.h"
+#include "../gfx.h"
+#include "8bpp.hpp"
+
+static FRenderer_8bpp iFRenderer_8bpp;
+
+void *Renderer_8bpp::MoveTo(const void *video, int x, int y)
+{
+	return (uint8 *)video + x + y * _screen.pitch;
+}
+
+void Renderer_8bpp::SetPixel(void *video, int x, int y, uint8 color)
+{
+	*((uint8 *)video + x + y * _screen.pitch) = color;
+}
+
+void Renderer_8bpp::SetPixelIfEmpty(void *video, int x, int y, uint8 color)
+{
+	uint8 *dst = (uint8 *)video + x + y * _screen.pitch;
+	if (*dst == 0) *dst = color;
+}
+
+void Renderer_8bpp::SetHorizontalLine(void *video, int width, uint8 color)
+{
+	memset(video, color, width);
+}
+
+void Renderer_8bpp::CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch)
+{
+	int direction = (height < 0) ? -1 : 1;
+	uint8 *dst = (uint8 *)video;
+	uint8 *usrc = (uint8 *)src;
+
+	height = abs(height);
+	for (; height > 0; height--) {
+		memcpy(dst, usrc, width);
+		usrc += src_pitch * direction;
+		dst += _screen.pitch * direction;
+	}
+}
+
+void Renderer_8bpp::CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)
+{
+	int direction = (height < 0) ? -1 : 1;
+	uint8 *udst = (uint8 *)dst;
+	uint8 *src = (uint8 *)video;
+
+	height = abs(height);
+	for (; height > 0; height--) {
+		memcpy(udst, src, width);
+		src += _screen.pitch * direction;
+		udst += dst_pitch * direction;
+	}
+}
+
+void Renderer_8bpp::MoveBuffer(void *video_dst, const void *video_src, int width, int height)
+{
+	uint8 *dst = (uint8 *)video_dst;
+	uint8 *src = (uint8 *)video_src;
+
+	for (; height > 0; height--) {
+		memmove(dst, src, width);
+		src += _screen.pitch;
+		dst += _screen.pitch;
+	}
+}
+
+int Renderer_8bpp::BufferSize(int width, int height)
+{
+	return width * height;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/renderer/8bpp.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,29 @@
+/* $Id$ */
+
+/** @file 8bpp.hpp */
+
+#ifndef RENDERER_8BPP_HPP
+#define RENDERER_8BPP_HPP
+
+#include "renderer.hpp"
+
+class Renderer_8bpp : public Renderer {
+public:
+	/* virtual */ void *MoveTo(const void *video, int x, int y);
+	/* virtual */ void SetPixel(void *video, int x, int y, uint8 color);
+	/* virtual */ void SetPixelIfEmpty(void *video, int x, int y, uint8 color);
+	/* virtual */ void SetHorizontalLine(void *video, int width, uint8 color);
+	/* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch);
+	/* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
+	/* virtual */ void MoveBuffer(void *video_dst, const void *video_src, int width, int height);
+	/* virtual */ int BufferSize(int width, int height);
+};
+
+class FRenderer_8bpp: public RendererFactory<FRenderer_8bpp> {
+public:
+	/* virtual */ const char *GetName() { return "8bpp"; }
+
+	/* virtual */ Renderer *CreateInstance() { return new Renderer_8bpp(); }
+};
+
+#endif /* RENDERER_8BPP_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/renderer/null.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,39 @@
+#include "../stdafx.h"
+#include "../gfx.h"
+#include "null.hpp"
+
+static FRenderer_Null iFRenderer_Null;
+
+void *Renderer_Null::MoveTo(const void *video, int x, int y)
+{
+	return NULL;
+}
+
+void Renderer_Null::SetPixel(void *video, int x, int y, uint8 color)
+{
+}
+
+void Renderer_Null::SetPixelIfEmpty(void *video, int x, int y, uint8 color)
+{
+}
+
+void Renderer_Null::SetHorizontalLine(void *video, int width, uint8 color)
+{
+}
+
+void Renderer_Null::CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch)
+{
+}
+
+void Renderer_Null::CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch)
+{
+}
+
+void Renderer_Null::MoveBuffer(void *video_dst, const void *video_src, int width, int height)
+{
+}
+
+int Renderer_Null::BufferSize(int width, int height)
+{
+	return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/renderer/null.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,29 @@
+/* $Id$ */
+
+/** @file null.hpp */
+
+#ifndef RENDERER_NULL_HPP
+#define RENDERER_NULL_HPP
+
+#include "renderer.hpp"
+
+class Renderer_Null : public Renderer {
+public:
+	/* virtual */ void *MoveTo(const void *video, int x, int y);
+	/* virtual */ void SetPixel(void *video, int x, int y, uint8 color);
+	/* virtual */ void SetPixelIfEmpty(void *video, int x, int y, uint8 color);
+	/* virtual */ void SetHorizontalLine(void *video, int width, uint8 color);
+	/* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch);
+	/* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch);
+	/* virtual */ void MoveBuffer(void *video_dst, const void *video_src, int width, int height);
+	/* virtual */ int BufferSize(int width, int height);
+};
+
+class FRenderer_Null: public RendererFactory<FRenderer_Null> {
+public:
+	/* virtual */ const char *GetName() { return "null"; }
+
+	/* virtual */ Renderer *CreateInstance() { return new Renderer_Null(); }
+};
+
+#endif /* RENDERER_NULL_HPP */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/renderer/renderer.hpp	Tue Jun 12 20:24:12 2007 +0000
@@ -0,0 +1,165 @@
+/* $Id$ */
+
+/** @file renderer.hpp */
+
+#ifndef RENDERER_HPP
+#define RENDERER_HPP
+
+#include <string>
+#include <map>
+
+class Renderer {
+public:
+	virtual ~Renderer() { }
+
+	/**
+	 * Move the destination pointer the requested amount x and y, keeping in mind
+	 *  any pitch and bpp of the renderer.
+	 * @param video The destination pointer (video-buffer) to scroll.
+	 * @param x How much you want to scroll to the right.
+	 * @param y How much you want to scroll to the bottom.
+	 * @return A new destination pointer moved the the requested place.
+	 */
+	virtual void *MoveTo(const void *video, int x, int y) = 0;
+
+	/**
+	 * Draw a pixel with a given color on the video-buffer.
+	 * @param video The destination pointer (video-buffer).
+	 * @param x The x position within video-buffer.
+	 * @param y The y position within video-buffer.
+	 * @param color A 8bpp mapping color.
+	 */
+	virtual void SetPixel(void *video, int x, int y, uint8 color) = 0;
+
+	/**
+	 * Draw a pixel with a given color on the video-buffer if there is currently a black pixel.
+	 * @param video The destination pointer (video-buffer).
+	 * @param x The x position within video-buffer.
+	 * @param y The y position within video-buffer.
+	 * @param color A 8bpp mapping color.
+	 */
+	virtual void SetPixelIfEmpty(void *video, int x, int y, uint8 color) = 0;
+
+	/**
+	 * Make a single horizontal line in a single color on the video-buffer.
+	 * @param video The destination pointer (video-buffer).
+	 * @param width The lenght of the line.
+	 * @param color A 8bpp mapping color.
+	 */
+	virtual void SetHorizontalLine(void *video, int width, uint8 color) = 0;
+
+	/**
+	 * Copy from a buffer to the screen.
+	 * @param video The destionation pointer (video-buffer).
+	 * @param src The buffer from which the data will be read.
+	 * @param width The width of the buffer.
+	 * @param height The height of the buffer.
+	 * @param src_pitch The pitch (byte per line) of the source buffer.
+	 */
+	virtual void CopyFromBuffer(void *video, const void *src, int width, int height, int src_pitch) = 0;
+
+	/**
+	 * Copy from the screen to a buffer.
+	 * @param video The destination pointer (video-buffer).
+	 * @param dst The buffer in which the data will be stored.
+	 * @param width The width of the buffer.
+	 * @param height The height of the buffer.
+	 * @param dst_pitch The pitch (byte per line) of the destination buffer.
+	 */
+	virtual void CopyToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) = 0;
+
+	/**
+	 * Move the videobuffer some places (via memmove).
+	 * @param video_dst The destination pointer (video-buffer).
+	 * @param video_src The source pointer (video-buffer).
+	 * @param width The width of the buffer to move.
+	 * @param height The height of the buffer to move.
+	 */
+	virtual void MoveBuffer(void *video_dst, const void *video_src, int width, int height) = 0;
+
+	/**
+	 * Calculate how much memory there is needed for an image of this size in the video-buffer.
+	 * @param width The width of the buffer-to-be.
+	 * @param height The height of the buffer-to-be.
+	 * @return The size needed for the buffer.
+	 */
+	virtual int BufferSize(int width, int height) = 0;
+};
+
+/**
+ * The factory, keeping track of all renderers.
+ */
+class RendererFactoryBase {
+private:
+	char *name;
+	typedef std::map<std::string, RendererFactoryBase *> Renderers;
+
+	static Renderers &GetRenderers()
+	{
+		static Renderers &s_renderers = *new Renderers();
+		return s_renderers;
+	}
+
+protected:
+	/**
+	 * Register a renderer internally, based on his bpp.
+	 * @param name the name of the renderer.
+	 * @note an assert() will be trigger if 2 renderers with the same bpp try to register.
+	 */
+	void RegisterRenderer(const char *name)
+	{
+		/* Don't register nameless Renderers */
+		if (name == NULL) return;
+
+		this->name = strdup(name);
+		std::pair<Renderers::iterator, bool> P = GetRenderers().insert(Renderers::value_type(name, this));
+		assert(P.second);
+	}
+
+public:
+	RendererFactoryBase() :
+		name(NULL)
+	{ }
+
+	virtual ~RendererFactoryBase() { if (this->name != NULL) GetRenderers().erase(this->name); free(this->name); }
+
+	/**
+	 * Find the requested renderer and return his class-instance.
+	 * @param name the renderer to select.
+	 */
+	static Renderer *SelectRenderer(const char *name)
+	{
+		if (GetRenderers().size() == 0) return NULL;
+
+		Renderers::iterator it = GetRenderers().begin();
+		for (; it != GetRenderers().end(); it++) {
+			RendererFactoryBase *r = (*it).second;
+			if (strcasecmp(name, r->name) == 0) {
+				return r->CreateInstance();
+			}
+		}
+		return NULL;
+	}
+
+	/**
+	 * Create an instance of this Renderer-class.
+	 */
+	virtual Renderer *CreateInstance() = 0;
+};
+
+/**
+ * A template factory, so ->GetBpp() works correctly. This because else some compiler will complain.
+ */
+template <class T>
+class RendererFactory: public RendererFactoryBase {
+public:
+	RendererFactory() { this->RegisterRenderer(((T *)this)->GetName()); }
+
+	/**
+	 * Get the name for this renderer.
+	 */
+	const char *GetName();
+};
+
+
+#endif /* RENDERER_HPP */
--- a/src/screenshot.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/screenshot.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -14,6 +14,7 @@
 #include "variables.h"
 #include "date.h"
 #include "helpers.hpp"
+#include "blitter/blitter.hpp"
 #include "fileio.h"
 
 char _screenshot_format_name[8];
@@ -22,7 +23,7 @@
 ScreenshotType current_screenshot_type;
 
 /* called by the ScreenShot proc to generate screenshot lines. */
-typedef void ScreenshotCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n);
+typedef void ScreenshotCallback(void *userdata, void *buf, uint y, uint pitch, uint n);
 typedef bool ScreenshotHandlerProc(const char *name, ScreenshotCallback *callb, void *userdata, uint w, uint h, int pixelformat, const Colour *palette);
 
 struct ScreenshotFormat {
@@ -72,10 +73,11 @@
 	FILE *f;
 	uint i, padw;
 	uint n, maxlines;
+	uint pal_size = 0;
+	uint bpp = pixelformat / 8;
 
-	/* only implemented for 8bit images so far. */
-	if (pixelformat != 8)
-		return false;
+	/* only implemented for 8bit and 32bit images so far. */
+	if (pixelformat != 8 && pixelformat != 32) return false;
 
 	f = fopen(name, "wb");
 	if (f == NULL) return false;
@@ -83,18 +85,20 @@
 	/* each scanline must be aligned on a 32bit boundary */
 	padw = ALIGN(w, 4);
 
+	if (pixelformat == 8) pal_size = sizeof(RgbQuad) * 256;
+
 	/* setup the file header */
 	bfh.type = TO_LE16('MB');
-	bfh.size = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256 + padw * h);
+	bfh.size = TO_LE32(sizeof(bfh) + sizeof(bih) + pal_size + padw * h * bpp);
 	bfh.reserved = 0;
-	bfh.off_bits = TO_LE32(sizeof(bfh) + sizeof(bih) + sizeof(RgbQuad) * 256);
+	bfh.off_bits = TO_LE32(sizeof(bfh) + sizeof(bih) + pal_size);
 
 	/* setup the info header */
 	bih.size = TO_LE32(sizeof(BitmapInfoHeader));
 	bih.width = TO_LE32(w);
 	bih.height = TO_LE32(h);
 	bih.planes = TO_LE16(1);
-	bih.bitcount = TO_LE16(8);
+	bih.bitcount = TO_LE16(pixelformat);
 	bih.compression = 0;
 	bih.sizeimage = 0;
 	bih.xpels = 0;
@@ -102,24 +106,26 @@
 	bih.clrused = 0;
 	bih.clrimp = 0;
 
-	/* convert the palette to the windows format */
-	for (i = 0; i != 256; i++) {
-		rq[i].red   = palette[i].r;
-		rq[i].green = palette[i].g;
-		rq[i].blue  = palette[i].b;
-		rq[i].reserved = 0;
+	if (pixelformat == 8) {
+		/* convert the palette to the windows format */
+		for (i = 0; i != 256; i++) {
+			rq[i].red   = palette[i].r;
+			rq[i].green = palette[i].g;
+			rq[i].blue  = palette[i].b;
+			rq[i].reserved = 0;
+		}
 	}
 
 	/* write file header and info header and palette */
 	if (fwrite(&bfh, sizeof(bfh), 1, f) != 1) return false;
 	if (fwrite(&bih, sizeof(bih), 1, f) != 1) return false;
-	if (fwrite(rq, sizeof(rq), 1, f) != 1) return false;
+	if (pixelformat == 8) if (fwrite(rq, sizeof(rq), 1, f) != 1) return false;
 
 	/* use by default 64k temp memory */
 	maxlines = clamp(65536 / padw, 16, 128);
 
 	/* now generate the bitmap bits */
-	Pixel *buff = MallocT<Pixel>(padw * maxlines); // by default generate 128 lines at a time.
+	void *buff = MallocT<uint8>(padw * maxlines * bpp); // by default generate 128 lines at a time.
 	if (buff == NULL) {
 		fclose(f);
 		return false;
@@ -137,7 +143,7 @@
 
 		/* write each line */
 		while (n)
-			if (fwrite(buff + (--n) * padw, padw, 1, f) != 1) {
+			if (fwrite((uint8 *)buff + (--n) * padw * bpp, padw * bpp, 1, f) != 1) {
 				free(buff);
 				fclose(f);
 				return false;
@@ -173,12 +179,12 @@
 	FILE *f;
 	uint i, y, n;
 	uint maxlines;
+	uint bpp = pixelformat / 8;
 	png_structp png_ptr;
 	png_infop info_ptr;
 
-	/* only implemented for 8bit images so far. */
-	if (pixelformat != 8)
-		return false;
+	/* only implemented for 8bit and 32bit images so far. */
+	if (pixelformat != 8 && pixelformat != 32) return false;
 
 	f = fopen(name, "wb");
 	if (f == NULL) return false;
@@ -207,31 +213,53 @@
 
 	png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
 
-	png_set_IHDR(png_ptr, info_ptr, w, h, pixelformat, PNG_COLOR_TYPE_PALETTE,
+	png_set_IHDR(png_ptr, info_ptr, w, h, 8, pixelformat == 8 ? PNG_COLOR_TYPE_PALETTE : PNG_COLOR_TYPE_RGB,
 		PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
 
-	/* convert the palette to the .PNG format. */
-	for (i = 0; i != 256; i++) {
-		rq[i].red   = palette[i].r;
-		rq[i].green = palette[i].g;
-		rq[i].blue  = palette[i].b;
+	if (pixelformat == 8) {
+		/* convert the palette to the .PNG format. */
+		for (i = 0; i != 256; i++) {
+			rq[i].red   = palette[i].r;
+			rq[i].green = palette[i].g;
+			rq[i].blue  = palette[i].b;
+		}
+
+		png_set_PLTE(png_ptr, info_ptr, rq, 256);
 	}
 
-	png_set_PLTE(png_ptr, info_ptr, rq, 256);
 	png_write_info(png_ptr, info_ptr);
 	png_set_flush(png_ptr, 512);
 
+	if (pixelformat == 32) {
+		png_color_8 sig_bit;
+
+		/* Save exact color/alpha resolution */
+		sig_bit.alpha = 0;
+		sig_bit.blue  = 8;
+		sig_bit.green = 8;
+		sig_bit.red   = 8;
+		sig_bit.gray  = 8;
+		png_set_sBIT(png_ptr, info_ptr, &sig_bit);
+
+#ifdef TTD_LITTLE_ENDIAN
+		png_set_bgr(png_ptr);
+		png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+#else
+		png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#endif
+	}
+
 	/* use by default 64k temp memory */
 	maxlines = clamp(65536 / w, 16, 128);
 
 	/* now generate the bitmap bits */
-	Pixel *buff = MallocT<Pixel>(w * maxlines); // by default generate 128 lines at a time.
+	void *buff = MallocT<uint8>(w * maxlines * bpp); // by default generate 128 lines at a time.
 	if (buff == NULL) {
 		png_destroy_write_struct(&png_ptr, &info_ptr);
 		fclose(f);
 		return false;
 	}
-	memset(buff, 0, w * maxlines); // zero the buffer to have the padding bytes set to 0
+	memset(buff, 0, w * maxlines * bpp);
 
 	y = 0;
 	do {
@@ -244,7 +272,7 @@
 
 		/* write them to png */
 		for (i = 0; i != n; i++)
-			png_write_row(png_ptr, buff + i * w);
+			png_write_row(png_ptr, (png_bytep)buff + i * w * bpp);
 	} while (y != h);
 
 	png_write_end(png_ptr, info_ptr);
@@ -288,6 +316,10 @@
 	PcxHeader pcx;
 	bool success;
 
+	if (pixelformat == 32) {
+		DEBUG(misc, 0, "Can't convert a 32bpp screenshot to PCX format. Please pick an other format.");
+		return false;
+	}
 	if (pixelformat != 8 || w == 0)
 		return false;
 
@@ -321,7 +353,7 @@
 	maxlines = clamp(65536 / w, 16, 128);
 
 	/* now generate the bitmap bits */
-	Pixel *buff = MallocT<Pixel>(w * maxlines); // by default generate 128 lines at a time.
+	uint8 *buff = MallocT<uint8>(w * maxlines); // by default generate 128 lines at a time.
 	if (buff == NULL) {
 		fclose(f);
 		return false;
@@ -340,14 +372,14 @@
 
 		/* write them to pcx */
 		for (i = 0; i != n; i++) {
-			const Pixel* bufp = buff + i * w;
+			const uint8 *bufp = buff + i * w;
 			byte runchar = bufp[0];
 			uint runcount = 1;
 			uint j;
 
 			/* for each pixel... */
 			for (j = 1; j < w; j++) {
-				Pixel ch = bufp[j];
+				uint8 ch = bufp[j];
 
 				if (ch != runchar || runcount >= 0x3f) {
 					if (runcount > 1 || (runchar & 0xC0) == 0xC0)
@@ -447,17 +479,14 @@
 }
 
 /* screenshot generator that dumps the current video buffer */
-static void CurrentScreenCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n)
+static void CurrentScreenCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
 {
-	for (; n > 0; --n) {
-		memcpy(buf, _screen.dst_ptr + y * _screen.pitch, _screen.width * sizeof(Pixel));
-		++y;
-		buf += pitch;
-	}
+	void *src = _screen.renderer->MoveTo(_screen.dst_ptr, 0, y);
+	_screen.renderer->CopyToBuffer(src, buf, _screen.width, n, pitch);
 }
 
 /* generate a large piece of the world */
-static void LargeWorldCallback(void *userdata, Pixel *buf, uint y, uint pitch, uint n)
+static void LargeWorldCallback(void *userdata, void *buf, uint y, uint pitch, uint n)
 {
 	ViewPort *vp = (ViewPort *)userdata;
 	DrawPixelInfo dpi, *old_dpi;
@@ -534,7 +563,7 @@
 static bool MakeSmallScreenshot()
 {
 	const ScreenshotFormat *sf = _screenshot_formats + _cur_screenshot_format;
-	return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, 8, _cur_palette);
+	return sf->proc(MakeScreenshotName(sf->extension), CurrentScreenCallback, NULL, _screen.width, _screen.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
 }
 
 static bool MakeWorldScreenshot()
@@ -553,7 +582,7 @@
 	vp.height = vp.virtual_height;
 
 	sf = _screenshot_formats + _cur_screenshot_format;
-	return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, 8, _cur_palette);
+	return sf->proc(MakeScreenshotName(sf->extension), LargeWorldCallback, &vp, vp.width, vp.height, BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(), _cur_palette);
 }
 
 bool MakeScreenshot()
--- a/src/settings.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/settings.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -1225,14 +1225,13 @@
 
 /* win32_v.c only settings */
 #ifdef WIN32
-extern bool _force_full_redraw, _double_size, _window_maximize;
+extern bool _force_full_redraw, _window_maximize;
 extern uint _display_hz, _fullscreen_bpp;
 
 static const SettingDescGlobVarList _win32_settings[] = {
 	 SDTG_VAR("display_hz",     SLE_UINT, S, 0, _display_hz,       0, 0, 120, 0, STR_NULL, NULL),
 	SDTG_BOOL("force_full_redraw",        S, 0, _force_full_redraw,false,        STR_NULL, NULL),
 	 SDTG_VAR("fullscreen_bpp", SLE_UINT, S, 0, _fullscreen_bpp,   8, 8,  32, 0, STR_NULL, NULL),
-	SDTG_BOOL("double_size",              S, 0, _double_size,      false,        STR_NULL, NULL),
 	SDTG_BOOL("window_maximize",          S, 0, _window_maximize,  false,        STR_NULL, NULL),
 	 SDTG_END()
 };
--- a/src/smallmap_gui.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/smallmap_gui.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -167,41 +167,23 @@
 	_legend_land_owners,
 };
 
-#if defined(OTTD_ALIGNMENT)
-	static inline void WRITE_PIXELS(Pixel* d, uint32 val)
-	{
-#	if defined(TTD_BIG_ENDIAN)
-		d[0] = GB(val, 24, 8);
-		d[1] = GB(val, 16, 8);
-		d[2] = GB(val,  8, 8);
-		d[3] = GB(val,  0, 8);
-#	elif defined(TTD_LITTLE_ENDIAN)
-		d[0] = GB(val,  0, 8);
-		d[1] = GB(val,  8, 8);
-		d[2] = GB(val, 16, 8);
-		d[3] = GB(val, 24, 8);
-#	endif
-	}
+static inline void WRITE_PIXELS(void *d, uint32 val)
+{
+	uint8 *val8 = (uint8 *)&val;
+	_screen.renderer->SetPixel(d, 0, 0, val8[0]);
+	_screen.renderer->SetPixel(d, 1, 0, val8[1]);
+	_screen.renderer->SetPixel(d, 2, 0, val8[2]);
+	_screen.renderer->SetPixel(d, 3, 0, val8[3]);
+}
 
-/* need to use OR, otherwise we will overwrite the wrong pixels at the edges :( */
-	static inline void WRITE_PIXELS_OR(Pixel *d, uint32 val)
-	{
-#	if defined(TTD_BIG_ENDIAN)
-		d[0] |= GB(val, 24, 8);
-		d[1] |= GB(val, 16, 8);
-		d[2] |= GB(val,  8, 8);
-		d[3] |= GB(val,  0, 8);
-#	elif defined(TTD_LITTLE_ENDIAN)
-		d[0] |= GB(val,  0, 8);
-		d[1] |= GB(val,  8, 8);
-		d[2] |= GB(val, 16, 8);
-		d[3] |= GB(val, 24, 8);
-#	endif
-	}
-#else
-#	define WRITE_PIXELS(dst, val)   *(uint32*)(dst) = (val);
-#	define WRITE_PIXELS_OR(dst,val) *(uint32*)(dst) |= (val);
-#endif
+static inline void WRITE_PIXELS_OR(void *d, uint32 val)
+{
+	uint8 *val8 = (uint8 *)&val;
+	_screen.renderer->SetPixelIfEmpty(d, 0, 0, val8[0]);
+	_screen.renderer->SetPixelIfEmpty(d, 1, 0, val8[1]);
+	_screen.renderer->SetPixelIfEmpty(d, 2, 0, val8[2]);
+	_screen.renderer->SetPixelIfEmpty(d, 3, 0, val8[3]);
+}
 
 #define MKCOLOR(x) TO_LE32X(x)
 
@@ -296,9 +278,9 @@
  * @param proc Pointer to the colour function
  * @see GetSmallMapPixels(TileIndex)
  */
-static void DrawSmallMapStuff(Pixel *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, GetSmallMapPixels *proc)
+static void DrawSmallMapStuff(void *dst, uint xc, uint yc, int pitch, int reps, uint32 mask, GetSmallMapPixels *proc)
 {
-	Pixel *dst_ptr_end = _screen.dst_ptr + _screen.width * _screen.height - _screen.width;
+	void *dst_ptr_end = _screen.renderer->MoveTo(_screen.dst_ptr, _screen.width, _screen.height - 1);
 
 	do {
 		/* check if the tile (xc,yc) is within the map range */
@@ -308,7 +290,7 @@
 				WRITE_PIXELS_OR(dst, proc(TileXY(xc, yc)) & mask);
 		}
 	/* switch to next tile in the column */
-	} while (xc++, yc++, dst += pitch, --reps != 0);
+	} while (xc++, yc++, dst = _screen.renderer->MoveTo(dst, pitch, 0), --reps != 0);
 }
 
 
@@ -530,7 +512,7 @@
 {
 	DrawPixelInfo *old_dpi;
 	int dx,dy, x, y, x2, y2;
-	Pixel *ptr;
+	void *ptr;
 	int tile_x;
 	int tile_y;
 	ViewPort *vp;
@@ -582,7 +564,7 @@
 		}
 	}
 
-	ptr = dpi->dst_ptr - dx - 4;
+	ptr = _screen.renderer->MoveTo(dpi->dst_ptr, -dx - 4, 0);
 	x = - dx - 4;
 	y = 0;
 
@@ -609,7 +591,6 @@
 		/* number of lines */
 		reps = (dpi->height - y + 1) / 2;
 		if (reps > 0) {
-//			assert(ptr >= dpi->dst_ptr);
 			DrawSmallMapStuff(ptr, tile_x, tile_y, dpi->pitch * 2, reps, mask, _smallmap_draw_procs[type]);
 		}
 
@@ -617,13 +598,13 @@
 		if (y == 0) {
 			tile_y++;
 			y++;
-			ptr += dpi->pitch;
+			ptr = _screen.renderer->MoveTo(ptr, 0, 1);
 		} else {
 			tile_x--;
 			y--;
-			ptr -= dpi->pitch;
+			ptr = _screen.renderer->MoveTo(ptr, 0, -1);
 		}
-		ptr += 2;
+		ptr = _screen.renderer->MoveTo(ptr, 2, 0);
 		x += 2;
 	}
 
@@ -666,12 +647,11 @@
 				}
 
 				/* Calculate pointer to pixel and the color */
-				ptr = dpi->dst_ptr + y * dpi->pitch + x;
 				color = (type == 1) ? _vehicle_type_colors[v->type] : 0xF;
 
 				/* And draw either one or two pixels depending on clipping */
-				ptr[0] = color;
-				if (!skip) ptr[1] = color;
+				_screen.renderer->SetPixel(dpi->dst_ptr, x, y, color);
+				if (!skip) _screen.renderer->SetPixel(dpi->dst_ptr, x + 1, y, color);;
 			}
 		}
 	}
--- a/src/texteff.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/texteff.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -54,9 +54,7 @@
 /* The chatbox grows from the bottom so the coordinates are pixels from
  * the left and pixels from the bottom. The height is the maximum height */
 static const Oblong _textmsg_box = {10, 30, 500, 150};
-static Pixel _textmessage_backup[150 * 500]; // (height * width)
-
-extern void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch);
+static uint8 _textmessage_backup[150 * 500 * 4]; // (height * width)
 
 static inline uint GetTextMessageCount()
 {
@@ -163,11 +161,7 @@
 
 		_textmessage_visible = false;
 		/* Put our 'shot' back to the screen */
-		memcpy_pitch(
-			_screen.dst_ptr + x + y * _screen.pitch,
-			_textmessage_backup,
-			width, height, _textmsg_box.width, _screen.pitch);
-
+		_screen.renderer->CopyFromBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
 		/* And make sure it is updated next time */
 		_video_driver->make_dirty(x, y, width, height);
 
@@ -227,10 +221,7 @@
 	if (width <= 0 || height <= 0) return;
 
 	/* Make a copy of the screen as it is before painting (for undraw) */
-	memcpy_pitch(
-		_textmessage_backup,
-		_screen.dst_ptr + x + y * _screen.pitch,
-		width, height, _screen.pitch, _textmsg_box.width);
+	_screen.renderer->CopyToBuffer(_screen.renderer->MoveTo(_screen.dst_ptr, x, y), _textmessage_backup, width, height, _textmsg_box.width);
 
 	_cur_dpi = &_screen; // switch to _screen painting
 
--- a/src/video/cocoa_v.mm	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/video/cocoa_v.mm	Tue Jun 12 20:24:12 2007 +0000
@@ -69,6 +69,7 @@
 #include "../macros.h"
 #include "../os/macosx/splash.h"
 #include "../variables.h"
+#include "../blitter/blitter.hpp"
 #include "cocoa_v.h"
 #include "cocoa_keys.h"
 
@@ -950,6 +951,10 @@
 
 static void QZ_UpdateWindowPalette(uint start, uint count)
 {
+	/* We can only update the palette in 8bpp for now */
+	/* TODO -- We need support for other bpps too! */
+	if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
+
 	uint i;
 
 	switch (_cocoa_video_data.device_bpp) {
--- a/src/video/dedicated_v.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/video/dedicated_v.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -13,6 +13,7 @@
 #include "../console.h"
 #include "../variables.h"
 #include "../genworld.h"
+#include "../blitter/blitter.hpp"
 #include "dedicated_v.h"
 
 #ifdef BEOS_NET_SERVER
@@ -112,7 +113,7 @@
 #endif
 
 
-static Pixel *_dedicated_video_mem;
+static void *_dedicated_video_mem;
 
 extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
 extern void SwitchMode(int new_mode);
@@ -120,9 +121,14 @@
 
 static const char *DedicatedVideoStart(const char * const *parm)
 {
+	int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
+	if (bpp == 0) _dedicated_video_mem = NULL;
+	else          _dedicated_video_mem = malloc(_cur_resolution[0] * _cur_resolution[1] * (bpp / 8));
+
 	_screen.width = _screen.pitch = _cur_resolution[0];
 	_screen.height = _cur_resolution[1];
-	_dedicated_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel));
+	_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
+	if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
 
 	SetDebugString("net=6");
 
--- a/src/video/null_v.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/video/null_v.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -5,19 +5,23 @@
 #include "../gfx.h"
 #include "../variables.h"
 #include "../window.h"
+#include "../debug.h"
+#include "../blitter/blitter.hpp"
 #include "null_v.h"
 
-static Pixel *_null_video_mem = NULL;
-
 static const char* NullVideoStart(const char* const* parm)
 {
 	_screen.width = _screen.pitch = _cur_resolution[0];
 	_screen.height = _cur_resolution[1];
-	_null_video_mem = (Pixel *)malloc(_cur_resolution[0] * _cur_resolution[1] * sizeof(Pixel));
+	/* Do not render, nor blit */
+	DEBUG(misc, 1, "Forcing blitter 'null'...");
+	BlitterFactoryBase::SelectBlitter("null");
+	_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
+	if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
 	return NULL;
 }
 
-static void NullVideoStop() { free(_null_video_mem); }
+static void NullVideoStop() { }
 
 static void NullVideoMakeDirty(int left, int top, int width, int height) {}
 
@@ -27,7 +31,7 @@
 
 	for (i = 0; i < 1000; i++) {
 		GameLoop();
-		_screen.dst_ptr = _null_video_mem;
+		_screen.dst_ptr = NULL;
 		UpdateWindows();
 	}
 }
--- a/src/video/sdl_v.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/video/sdl_v.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -13,6 +13,8 @@
 #include "../window.h"
 #include "../network/network.h"
 #include "../variables.h"
+#include "../blitter/blitter.hpp"
+#include "../renderer/renderer.hpp"
 #include "sdl_v.h"
 #include <SDL.h>
 
@@ -36,6 +38,10 @@
 
 static void UpdatePalette(uint start, uint count)
 {
+	/* We can only update the palette in 8bpp for now */
+	/* TODO -- We need support for other bpps too! */
+	if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
+
 	SDL_Color pal[256];
 	uint i;
 
@@ -172,10 +178,13 @@
 	extern const char _openttd_revision[];
 	SDL_Surface *newscreen, *icon;
 	char caption[50];
+	int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 
 	GetAvailableVideoMode(&w, &h);
 
-	DEBUG(driver, 1, "SDL: using mode %dx%d", w, h);
+	DEBUG(driver, 1, "SDL: using mode %dx%dx%d", w, h, bpp);
+
+	if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
 
 	/* Give the application an icon */
 	icon = SDL_CALL SDL_LoadBMP(ICON_DIR PATHSEP "openttd.32.bmp");
@@ -189,14 +198,15 @@
 	}
 
 	// DO NOT CHANGE TO HWSURFACE, IT DOES NOT WORK
-	newscreen = SDL_CALL SDL_SetVideoMode(w, h, 8, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
+	newscreen = SDL_CALL SDL_SetVideoMode(w, h, bpp, SDL_SWSURFACE | SDL_HWPALETTE | (_fullscreen ? SDL_FULLSCREEN : SDL_RESIZABLE));
 	if (newscreen == NULL)
 		return false;
 
 	_screen.width = newscreen->w;
 	_screen.height = newscreen->h;
-	_screen.pitch = newscreen->pitch / sizeof(Pixel);
-
+	_screen.pitch = newscreen->pitch / (bpp / 8);
+	_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
+	if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
 	_sdl_screen = newscreen;
 	InitPalette();
 
@@ -469,7 +479,7 @@
 				(keys[SDLK_DOWN]  ? 8 : 0);
 			GameLoop();
 
-			_screen.dst_ptr = (Pixel*)_sdl_screen->pixels;
+			_screen.dst_ptr = _sdl_screen->pixels;
 			UpdateWindows();
 			if (++pal_tick > 4) {
 				CheckPaletteAnim();
@@ -478,7 +488,7 @@
 			DrawSurfaceToScreen();
 		} else {
 			SDL_CALL SDL_Delay(1);
-			_screen.dst_ptr = (Pixel*)_sdl_screen->pixels;
+			_screen.dst_ptr = _sdl_screen->pixels;
 			DrawTextMessage();
 			DrawMouseCursor();
 			DrawSurfaceToScreen();
--- a/src/video/win32_v.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/video/win32_v.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -9,6 +9,7 @@
 #include "../variables.h"
 #include "../win32.h"
 #include "../window.h"
+#include "../blitter/blitter.hpp"
 #include "win32_v.h"
 #include <windows.h>
 #include <tchar.h>
@@ -16,22 +17,18 @@
 static struct {
 	HWND main_wnd;
 	HBITMAP dib_sect;
-	Pixel *bitmap_bits;
-	Pixel *buffer_bits;
-	Pixel *alloced_bits;
+	void *buffer_bits;
 	HPALETTE gdi_palette;
 	int width;
 	int height;
 	int width_org;
 	int height_org;
 	bool fullscreen;
-	bool double_size;
 	bool has_focus;
 	bool running;
 } _wnd;
 
 bool _force_full_redraw;
-bool _double_size;
 bool _window_maximize;
 uint _display_hz;
 uint _fullscreen_bpp;
@@ -63,6 +60,10 @@
 
 static void UpdatePalette(HDC dc, uint start, uint count)
 {
+	/* We can only update the palette in 8bpp for now */
+	/* TODO -- We need support for other bpps too! */
+	if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) return;
+
 	RGBQUAD rgb[256];
 	uint i;
 
@@ -136,11 +137,6 @@
 
 static void ClientSizeChanged(int w, int h)
 {
-	if (_wnd.double_size) {
-		w /= 2;
-		h /= 2;
-	}
-
 	// allocate new dib section of the new size
 	if (AllocateDibSection(w, h)) {
 		// mark all palette colors dirty
@@ -319,11 +315,6 @@
 				DrawMouseCursor();
 			}
 
-			if (_wnd.double_size) {
-				x /= 2;
-				y /= 2;
-			}
-
 			if (_cursor.fix_at) {
 				int dx = x - _cursor.pos.x;
 				int dy = y - _cursor.pos.y;
@@ -334,10 +325,6 @@
 					pt.x = _cursor.pos.x;
 					pt.y = _cursor.pos.y;
 
-					if (_wnd.double_size) {
-						pt.x *= 2;
-						pt.y *= 2;
-					}
 					ClientToScreen(hwnd, &pt);
 					SetCursorPos(pt.x, pt.y);
 				}
@@ -400,13 +387,6 @@
 			 * WM_KEYDOWN only handles CTRL+ commands and special keys like VK_LEFT, etc. */
 			if (keycode == 0 || (keycode > WKC_PAUSE && GB(keycode, 13, 4) == 0)) return 0;
 
-			if (keycode == ('D' | WKC_CTRL) && !_wnd.fullscreen) {
-				_double_size ^= 1;
-				_wnd.double_size = _double_size;
-				ClientSizeChanged(_wnd.width, _wnd.height);
-				MarkWholeScreenDirty();
-			}
-
 			HandleKeypress(0 | (keycode << 16));
 			return 0;
 		}
@@ -455,16 +435,8 @@
 
 			w = r->right - r->left - (r2.right - r2.left);
 			h = r->bottom - r->top - (r2.bottom - r2.top);
-			if (_wnd.double_size) {
-				w /= 2;
-				h /= 2;
-			}
 			w = clamp(w, 64, MAX_SCREEN_WIDTH);
 			h = clamp(h, 64, MAX_SCREEN_HEIGHT);
-			if (_wnd.double_size) {
-				w *= 2;
-				h *= 2;
-			}
 			SetRect(&r2, 0, 0, w, h);
 
 			AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE);
@@ -567,8 +539,6 @@
 {
 	_fullscreen = full_screen;
 
-	_wnd.double_size = _double_size && !full_screen;
-
 	// recreate window?
 	if ((full_screen || _wnd.fullscreen) && _wnd.main_wnd) {
 		DestroyWindow(_wnd.main_wnd);
@@ -581,6 +551,9 @@
 	if (full_screen) {
 		DEVMODE settings;
 
+		/* Make sure we are always at least the screen-depth of the blitter */
+		if (_fullscreen_bpp < BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth()) _fullscreen_bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
+
 		memset(&settings, 0, sizeof(settings));
 		settings.dmSize = sizeof(settings);
 		settings.dmFields =
@@ -649,49 +622,39 @@
 {
 	BITMAPINFO *bi;
 	HDC dc;
+	int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 
 	w = clamp(w, 64, MAX_SCREEN_WIDTH);
 	h = clamp(h, 64, MAX_SCREEN_HEIGHT);
 
+	if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals");
+
 	if (w == _screen.width && h == _screen.height)
 		return false;
 
 	_screen.width = w;
 	_screen.pitch = ALIGN(w, 4);
 	_screen.height = h;
-
-	if (_wnd.alloced_bits) {
-		free(_wnd.alloced_bits);
-		_wnd.alloced_bits = NULL;
-	}
-
+	_screen.renderer = RendererFactoryBase::SelectRenderer(BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
+	if (_screen.renderer == NULL) error("Couldn't load the renderer '%s' the selected blitter depends on", BlitterFactoryBase::GetCurrentBlitter()->GetRenderer());
 	bi = (BITMAPINFO*)alloca(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
 	memset(bi, 0, sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
 	bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
 
-	if (_wnd.double_size) {
-		w = ALIGN(w, 4);
-		_wnd.alloced_bits = _wnd.buffer_bits = (Pixel *)malloc(w * h * sizeof(Pixel));
-		w *= 2;
-		h *= 2;
-	}
-
 	bi->bmiHeader.biWidth = _wnd.width = w;
 	bi->bmiHeader.biHeight = -(_wnd.height = h);
 
 	bi->bmiHeader.biPlanes = 1;
-	bi->bmiHeader.biBitCount = 8;
+	bi->bmiHeader.biBitCount = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth();
 	bi->bmiHeader.biCompression = BI_RGB;
 
 	if (_wnd.dib_sect) DeleteObject(_wnd.dib_sect);
 
 	dc = GetDC(0);
-	_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.bitmap_bits, NULL, 0);
+	_wnd.dib_sect = CreateDIBSection(dc, bi, DIB_RGB_COLORS, (VOID**)&_wnd.buffer_bits, NULL, 0);
 	if (_wnd.dib_sect == NULL) error("CreateDIBSection failed");
 	ReleaseDC(0, dc);
 
-	if (!_wnd.double_size) _wnd.buffer_bits = _wnd.bitmap_bits;
-
 	return true;
 }
 
@@ -723,7 +686,7 @@
 	 * Doesn't really matter since we don't pass a string anyways, but still
 	 * a letdown */
 	for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) {
-		if (dm.dmBitsPerPel == 8 && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
+		if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && IS_INT_INSIDE(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) &&
 				IS_INT_INSIDE(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) {
 			uint j;
 
@@ -786,43 +749,13 @@
 #if !defined(WINCE)
 	if (_wnd.fullscreen) ChangeDisplaySettings(NULL, 0);
 #endif
-	if (_wnd.double_size) {
-		_cur_resolution[0] *= 2;
-		_cur_resolution[1] *= 2;
-	}
-
 	MyShowCursor(true);
 }
 
-// simple upscaler by 2
-static void filter(int left, int top, int width, int height)
-{
-	uint p = _screen.pitch;
-	const Pixel *s = _wnd.buffer_bits + top * p + left;
-	Pixel *d = _wnd.bitmap_bits + top * p * 4 + left * 2;
-
-	for (; height > 0; height--) {
-		int i;
-
-		for (i = 0; i != width; i++) {
-			d[i * 2] = d[i * 2 + 1] = d[i * 2 + p * 2] = d[i * 2 + 1 + p * 2] = s[i];
-		}
-		s += p;
-		d += p * 4;
-	}
-}
-
 static void Win32GdiMakeDirty(int left, int top, int width, int height)
 {
 	RECT r = { left, top, left + width, top + height };
 
-	if (_wnd.double_size) {
-		filter(left, top, width, height);
-		r.left *= 2;
-		r.top *= 2;
-		r.right *= 2;
-		r.bottom *= 2;
-	}
 	InvalidateRect(_wnd.main_wnd, &r, FALSE);
 }
 
--- a/src/viewport.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/viewport.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -1269,7 +1269,7 @@
 	x = UnScaleByZoom(vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
 	y = UnScaleByZoom(vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
 
-	vd.dpi.dst_ptr = old_dpi->dst_ptr + x - old_dpi->left + (y - old_dpi->top) * old_dpi->pitch;
+	vd.dpi.dst_ptr = _screen.renderer->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top);
 
 	vd.parent_list = parent_list;
 	vd.eof_parent_list = endof(parent_list);
--- a/src/window.cpp	Tue Jun 12 18:10:14 2007 +0000
+++ b/src/window.cpp	Tue Jun 12 20:24:12 2007 +0000
@@ -270,7 +270,7 @@
 		dp->left = left - (*wz)->left;
 		dp->top = top - (*wz)->top;
 		dp->pitch = _screen.pitch;
-		dp->dst_ptr = _screen.dst_ptr + top * _screen.pitch + left;
+		dp->dst_ptr = _screen.renderer->MoveTo(_screen.dst_ptr, left, top);
 		dp->zoom = ZOOM_LVL_NORMAL;
 		CallWindowEventNP(*wz, WE_PAINT);
 	}