diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj
index e395f48423..e7379545f9 100644
--- a/projects/openttd.vcproj
+++ b/projects/openttd.vcproj
@@ -979,6 +979,12 @@
+
+
+
+
@@ -996,6 +1002,25 @@
RelativePath=".\..\src\spriteloader\spriteloader.hpp">
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
index eee9ba6e4e..613a613306 100644
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1527,6 +1527,14 @@
RelativePath=".\..\src\blitter\8bpp_simple.hpp"
>
+
+
+
+
@@ -1548,6 +1556,30 @@
>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/source.list b/source.list
index 98e55bd006..4be5cf88cd 100644
--- a/source.list
+++ b/source.list
@@ -297,6 +297,8 @@ blitter/8bpp_optimized.cpp
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.cpp
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
diff --git a/src/blitter/8bpp_debug.cpp b/src/blitter/8bpp_debug.cpp
index 3f4c0b046f..3a9b52d2ab 100644
--- a/src/blitter/8bpp_debug.cpp
+++ b/src/blitter/8bpp_debug.cpp
@@ -12,12 +12,12 @@ static FBlitter_8bppDebug iFBlitter_8bppDebug;
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;
diff --git a/src/blitter/8bpp_debug.hpp b/src/blitter/8bpp_debug.hpp
index 443fb20c4e..7b8484f704 100644
--- a/src/blitter/8bpp_debug.hpp
+++ b/src/blitter/8bpp_debug.hpp
@@ -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 {
diff --git a/src/blitter/8bpp_optimized.cpp b/src/blitter/8bpp_optimized.cpp
index 7a105544cc..9af922e30b 100644
--- a/src/blitter/8bpp_optimized.cpp
+++ b/src/blitter/8bpp_optimized.cpp
@@ -12,16 +12,16 @@ static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
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++) {
diff --git a/src/blitter/8bpp_optimized.hpp b/src/blitter/8bpp_optimized.hpp
index b7f8b694f8..540e9d1c6e 100644
--- a/src/blitter/8bpp_optimized.hpp
+++ b/src/blitter/8bpp_optimized.hpp
@@ -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 {
diff --git a/src/blitter/8bpp_simple.cpp b/src/blitter/8bpp_simple.cpp
index 170afa460e..010066f8a8 100644
--- a/src/blitter/8bpp_simple.cpp
+++ b/src/blitter/8bpp_simple.cpp
@@ -11,12 +11,12 @@ static FBlitter_8bppSimple iFBlitter_8bppSimple;
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;
diff --git a/src/blitter/8bpp_simple.hpp b/src/blitter/8bpp_simple.hpp
index f472457297..1188e509d6 100644
--- a/src/blitter/8bpp_simple.hpp
+++ b/src/blitter/8bpp_simple.hpp
@@ -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 {
diff --git a/src/blitter/blitter.hpp b/src/blitter/blitter.hpp
index 1114dbf58f..b2e0edfe37 100644
--- a/src/blitter/blitter.hpp
+++ b/src/blitter/blitter.hpp
@@ -53,6 +53,11 @@ public:
*/
virtual Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator) = 0;
+ /**
+ * Get the renderer this class depends on.
+ */
+ virtual const char *GetRenderer() = 0;
+
virtual ~Blitter() { }
};
diff --git a/src/blitter/null.cpp b/src/blitter/null.cpp
new file mode 100644
index 0000000000..1aad792a16
--- /dev/null
+++ b/src/blitter/null.cpp
@@ -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;
+}
diff --git a/src/blitter/null.hpp b/src/blitter/null.hpp
new file mode 100644
index 0000000000..5278bd4746
--- /dev/null
+++ b/src/blitter/null.hpp
@@ -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 {
+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 */
diff --git a/src/gfx.cpp b/src/gfx.cpp
index 3117d17824..332015ef34 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -50,7 +50,7 @@ static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
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 @@ static byte _string_colorremap[3];
#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 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* 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 @@ void GfxScroll(int left, int top, int width, int height, int xo, int yo)
/* 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 GfxScroll(int left, int top, int width, int height, int xo, int yo)
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 @@ void GfxFillRect(int left, int top, int right, int bottom, int color)
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 @@ void DoPaletteAnimations()
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 @@ void DoPaletteAnimations()
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 @@ void UndrawMouseCursor()
{
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 @@ void DrawMouseCursor()
_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 @@ bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int heigh
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;
diff --git a/src/gfx.h b/src/gfx.h
index a74ad4253e..c91cce4b62 100644
--- a/src/gfx.h
+++ b/src/gfx.h
@@ -7,6 +7,7 @@
#include "openttd.h"
#include "zoom.hpp"
+#include "renderer/renderer.hpp"
enum WindowKeyCodes {
WKC_SHIFT = 0x8000,
@@ -93,7 +94,6 @@ void GameLoop();
void CreateConsole();
typedef int32 CursorID;
-typedef byte Pixel;
struct Point {
int x,y;
@@ -134,10 +134,11 @@ struct CursorVars {
};
struct DrawPixelInfo {
- Pixel *dst_ptr;
+ void *dst_ptr;
int left, top, width, height;
int pitch;
ZoomLevel zoom;
+ Renderer *renderer;
};
struct Colour {
diff --git a/src/openttd.cpp b/src/openttd.cpp
index b6462bdb19..c3983aee1e 100644
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -402,6 +402,7 @@ int ttd_main(int argc, char *argv[])
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).
diff --git a/src/renderer/8bpp.cpp b/src/renderer/8bpp.cpp
new file mode 100644
index 0000000000..2f595c6c95
--- /dev/null
+++ b/src/renderer/8bpp.cpp
@@ -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;
+}
diff --git a/src/renderer/8bpp.hpp b/src/renderer/8bpp.hpp
new file mode 100644
index 0000000000..a8bb27a486
--- /dev/null
+++ b/src/renderer/8bpp.hpp
@@ -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 {
+public:
+ /* virtual */ const char *GetName() { return "8bpp"; }
+
+ /* virtual */ Renderer *CreateInstance() { return new Renderer_8bpp(); }
+};
+
+#endif /* RENDERER_8BPP_HPP */
diff --git a/src/renderer/null.cpp b/src/renderer/null.cpp
new file mode 100644
index 0000000000..fc68feaf2c
--- /dev/null
+++ b/src/renderer/null.cpp
@@ -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;
+}
diff --git a/src/renderer/null.hpp b/src/renderer/null.hpp
new file mode 100644
index 0000000000..1eb95bbdd7
--- /dev/null
+++ b/src/renderer/null.hpp
@@ -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 {
+public:
+ /* virtual */ const char *GetName() { return "null"; }
+
+ /* virtual */ Renderer *CreateInstance() { return new Renderer_Null(); }
+};
+
+#endif /* RENDERER_NULL_HPP */
diff --git a/src/renderer/renderer.hpp b/src/renderer/renderer.hpp
new file mode 100644
index 0000000000..7b7ad0f4fe
--- /dev/null
+++ b/src/renderer/renderer.hpp
@@ -0,0 +1,165 @@
+/* $Id$ */
+
+/** @file renderer.hpp */
+
+#ifndef RENDERER_HPP
+#define RENDERER_HPP
+
+#include
+#include