src/gfx.cpp
branchgamebalance
changeset 9913 e79cd19772dd
parent 9912 1ac8aac92385
equal deleted inserted replaced
9912:1ac8aac92385 9913:e79cd19772dd
    17 #include "table/control_codes.h"
    17 #include "table/control_codes.h"
    18 #include "fontcache.h"
    18 #include "fontcache.h"
    19 #include "genworld.h"
    19 #include "genworld.h"
    20 #include "debug.h"
    20 #include "debug.h"
    21 #include "zoom.hpp"
    21 #include "zoom.hpp"
    22 #include "blitter/blitter.hpp"
    22 #include "blitter/factory.hpp"
    23 
    23 
    24 #ifdef _DEBUG
    24 #ifdef _DEBUG
    25 bool _dbg_screen_rect;
    25 bool _dbg_screen_rect;
    26 #endif
    26 #endif
    27 
    27 
    48 
    48 
    49 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode);
    49 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode);
    50 
    50 
    51 FontSize _cur_fontsize;
    51 FontSize _cur_fontsize;
    52 static FontSize _last_fontsize;
    52 static FontSize _last_fontsize;
    53 static Pixel _cursor_backup[64 * 64];
    53 static uint8 _cursor_backup[64 * 64 * 4];
    54 static Rect _invalid_rect;
    54 static Rect _invalid_rect;
    55 static const byte *_color_remap_ptr;
    55 static const byte *_color_remap_ptr;
    56 static byte _string_colorremap[3];
    56 static byte _string_colorremap[3];
    57 
    57 
    58 #define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
    58 #define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
    59 static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
    59 static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
    60 
    60 
    61 void memcpy_pitch(void *dst, void *src, int w, int h, int srcpitch, int dstpitch)
       
    62 {
       
    63 	Pixel *dstp = (Pixel *)dst;
       
    64 	Pixel *srcp = (Pixel *)src;
       
    65 
       
    66 	assert(h >= 0);
       
    67 	for (; h != 0; --h) {
       
    68 		memcpy(dstp, srcp, w * sizeof(Pixel));
       
    69 		dstp += dstpitch;
       
    70 		srcp += srcpitch;
       
    71 	}
       
    72 }
       
    73 
       
    74 void GfxScroll(int left, int top, int width, int height, int xo, int yo)
    61 void GfxScroll(int left, int top, int width, int height, int xo, int yo)
    75 {
    62 {
    76 	const Pixel *src;
    63 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
    77 	Pixel *dst;
    64 	const void *src;
    78 	int p;
    65 	void *dst;
    79 	int ht;
       
    80 
    66 
    81 	if (xo == 0 && yo == 0) return;
    67 	if (xo == 0 && yo == 0) return;
    82 
    68 
    83 	if (_cursor.visible) UndrawMouseCursor();
    69 	if (_cursor.visible) UndrawMouseCursor();
    84 	UndrawTextMessage();
    70 	UndrawTextMessage();
    85 
    71 
    86 	p = _screen.pitch;
       
    87 
       
    88 	if (yo > 0) {
    72 	if (yo > 0) {
    89 		/*Calculate pointers */
    73 		/*Calculate pointers */
    90 		dst = _screen.dst_ptr + (top + height - 1) * p + left;
    74 		dst = blitter->MoveTo(_screen.dst_ptr, left, top + height - 1);
    91 		src = dst - yo * p;
    75 		src = blitter->MoveTo(dst, 0, -yo);
    92 
    76 
    93 		/* Decrease height and increase top */
    77 		/* Decrease height and increase top */
    94 		top += yo;
    78 		top += yo;
    95 		height -= yo;
    79 		height -= yo;
    96 		assert(height > 0);
    80 		assert(height > 0);
    97 
    81 
    98 		/* Adjust left & width */
    82 		/* Adjust left & width */
    99 		if (xo >= 0) {
    83 		if (xo >= 0) {
   100 			dst += xo;
    84 			dst = blitter->MoveTo(dst, xo, 0);
   101 			left += xo;
    85 			left += xo;
   102 			width -= xo;
    86 			width -= xo;
   103 		} else {
    87 		} else {
   104 			src -= xo;
    88 			src = blitter->MoveTo(src, -xo, 0);
   105 			width += xo;
    89 			width += xo;
   106 		}
    90 		}
   107 
    91 
   108 		for (ht = height; ht > 0; --ht) {
    92 		/* Negative height as we want to copy from bottom to top */
   109 			memcpy(dst, src, width * sizeof(Pixel));
    93 		blitter->CopyFromBuffer(dst, src, width, -height, _screen.pitch);
   110 			src -= p;
       
   111 			dst -= p;
       
   112 		}
       
   113 	} else {
    94 	} else {
   114 		/* Calculate pointers */
    95 		/* Calculate pointers */
   115 		dst = _screen.dst_ptr + top * p + left;
    96 		dst = blitter->MoveTo(_screen.dst_ptr, left, top);
   116 		src = dst - yo * p;
    97 		src = blitter->MoveTo(dst, 0, -yo);
   117 
    98 
   118 		/* Decrese height. (yo is <=0). */
    99 		/* Decrese height. (yo is <=0). */
   119 		height += yo;
   100 		height += yo;
   120 		assert(height > 0);
   101 		assert(height > 0);
   121 
   102 
   122 		/* Adjust left & width */
   103 		/* Adjust left & width */
   123 		if (xo >= 0) {
   104 		if (xo >= 0) {
   124 			dst += xo;
   105 			dst = blitter->MoveTo(dst, xo, 0);
   125 			left += xo;
   106 			left += xo;
   126 			width -= xo;
   107 			width -= xo;
   127 		} else {
   108 		} else {
   128 			src -= xo;
   109 			src = blitter->MoveTo(src, -xo, 0);
   129 			width += xo;
   110 			width += xo;
   130 		}
   111 		}
   131 
   112 
   132 		/* the y-displacement may be 0 therefore we have to use memmove,
   113 		/* the y-displacement may be 0 therefore we have to use memmove,
   133 		 * because source and destination may overlap */
   114 		 * because source and destination may overlap */
   134 		for (ht = height; ht > 0; --ht) {
   115 		blitter->MoveBuffer(dst, src, width, height);
   135 			memmove(dst, src, width * sizeof(Pixel));
       
   136 			src += p;
       
   137 			dst += p;
       
   138 		}
       
   139 	}
   116 	}
   140 	/* This part of the screen is now dirty. */
   117 	/* This part of the screen is now dirty. */
   141 	_video_driver->make_dirty(left, top, width, height);
   118 	_video_driver->make_dirty(left, top, width, height);
   142 }
   119 }
   143 
   120 
   144 
   121 
   145 void GfxFillRect(int left, int top, int right, int bottom, int color)
   122 void GfxFillRect(int left, int top, int right, int bottom, int color)
   146 {
   123 {
   147 	const DrawPixelInfo* dpi = _cur_dpi;
   124 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
   148 	Pixel *dst;
   125 	const DrawPixelInfo *dpi = _cur_dpi;
       
   126 	void *dst;
   149 	const int otop = top;
   127 	const int otop = top;
   150 	const int oleft = left;
   128 	const int oleft = left;
   151 
   129 
   152 	if (dpi->zoom != ZOOM_LVL_NORMAL) return;
   130 	if (dpi->zoom != ZOOM_LVL_NORMAL) return;
   153 	if (left > right || top > bottom) return;
   131 	if (left > right || top > bottom) return;
   164 	bottom = bottom - dpi->top + 1;
   142 	bottom = bottom - dpi->top + 1;
   165 	if (bottom > dpi->height) bottom = dpi->height;
   143 	if (bottom > dpi->height) bottom = dpi->height;
   166 	bottom -= top;
   144 	bottom -= top;
   167 	assert(bottom > 0);
   145 	assert(bottom > 0);
   168 
   146 
   169 	dst = dpi->dst_ptr + top * dpi->pitch + left;
   147 	dst = blitter->MoveTo(dpi->dst_ptr, left, top);
   170 
   148 
   171 	if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
   149 	if (!HASBIT(color, PALETTE_MODIFIER_GREYOUT)) {
   172 		if (!HASBIT(color, USE_COLORTABLE)) {
   150 		if (!HASBIT(color, USE_COLORTABLE)) {
   173 			do {
   151 			do {
   174 				memset(dst, color, right * sizeof(Pixel));
   152 				blitter->SetHorizontalLine(dst, right, (uint8)color);
   175 				dst += dpi->pitch;
   153 				dst = blitter->MoveTo(dst, 0, 1);
   176 			} while (--bottom);
   154 			} while (--bottom);
   177 		} else {
   155 		} else {
   178 			/* use colortable mode */
   156 			blitter->DrawColorMappingRect(dst, right, bottom, GB(color, 0, PALETTE_WIDTH));
   179 			const byte* ctab = GetNonSprite(GB(color, 0, PALETTE_WIDTH)) + 1;
       
   180 
       
   181 			do {
       
   182 				int i;
       
   183 				for (i = 0; i != right; i++) dst[i] = ctab[dst[i]];
       
   184 				dst += dpi->pitch;
       
   185 			} while (--bottom);
       
   186 		}
   157 		}
   187 	} else {
   158 	} else {
   188 		byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
   159 		byte bo = (oleft - left + dpi->left + otop - top + dpi->top) & 1;
   189 		do {
   160 		do {
   190 			int i;
   161 			for (int i = (bo ^= 1); i < right; i += 2) blitter->SetPixel(dst, i, 0, (uint8)color);
   191 			for (i = (bo ^= 1); i < right; i += 2) dst[i] = (byte)color;
   162 			dst = blitter->MoveTo(dst, 0, 1);
   192 			dst += dpi->pitch;
       
   193 		} while (--bottom > 0);
   163 		} while (--bottom > 0);
   194 	}
   164 	}
   195 }
   165 }
   196 
   166 
   197 static void GfxSetPixel(int x, int y, int color)
   167 static void GfxSetPixel(int x, int y, int color)
   198 {
   168 {
   199 	const DrawPixelInfo* dpi = _cur_dpi;
   169 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
   200 	if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top)<0 || y >= dpi->height)
   170 	const DrawPixelInfo *dpi = _cur_dpi;
   201 		return;
   171 
   202 	dpi->dst_ptr[y * dpi->pitch + x] = color;
   172 	if ((x -= dpi->left) < 0 || x >= dpi->width || (y -= dpi->top) < 0 || y >= dpi->height) return;
       
   173 	blitter->SetPixel(dpi->dst_ptr, x, y, color);
   203 }
   174 }
   204 
   175 
   205 void GfxDrawLine(int x, int y, int x2, int y2, int color)
   176 void GfxDrawLine(int x, int y, int x2, int y2, int color)
   206 {
   177 {
   207 	int dy;
   178 	int dy;
   815 	const ExtraPaletteValues *ev = &_extra_palette_values;
   786 	const ExtraPaletteValues *ev = &_extra_palette_values;
   816 	int c = _use_dos_palette ? 38 : 28;
   787 	int c = _use_dos_palette ? 38 : 28;
   817 	Colour old_val[38]; // max(38, 28)
   788 	Colour old_val[38]; // max(38, 28)
   818 	uint i;
   789 	uint i;
   819 	uint j;
   790 	uint j;
       
   791 	int old_tc = _timer_counter;
       
   792 
       
   793 	/* We can only update the palette in 8bpp for now */
       
   794 	/* TODO -- We need support for other bpps too! */
       
   795 	if (BlitterFactoryBase::GetCurrentBlitter() != NULL && BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() != 8) {
       
   796 		_timer_counter = 0;
       
   797 	}
   820 
   798 
   821 	d = &_cur_palette[217];
   799 	d = &_cur_palette[217];
   822 	memcpy(old_val, d, c * sizeof(*old_val));
   800 	memcpy(old_val, d, c * sizeof(*old_val));
   823 
   801 
   824 	/* Dark blue water */
   802 	/* Dark blue water */
   911 
   889 
   912 	if (memcmp(old_val, &_cur_palette[217], c * sizeof(*old_val)) != 0) {
   890 	if (memcmp(old_val, &_cur_palette[217], c * sizeof(*old_val)) != 0) {
   913 		if (_pal_first_dirty > 217) _pal_first_dirty = 217;
   891 		if (_pal_first_dirty > 217) _pal_first_dirty = 217;
   914 		if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c;
   892 		if (_pal_last_dirty < 217 + c) _pal_last_dirty = 217 + c;
   915 	}
   893 	}
       
   894 
       
   895 	if (old_tc != _timer_counter) _timer_counter = old_tc;
   916 }
   896 }
   917 
   897 
   918 
   898 
   919 void LoadStringWidthTable()
   899 void LoadStringWidthTable()
   920 {
   900 {
   956 }
   936 }
   957 
   937 
   958 void UndrawMouseCursor()
   938 void UndrawMouseCursor()
   959 {
   939 {
   960 	if (_cursor.visible) {
   940 	if (_cursor.visible) {
       
   941 		Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
   961 		_cursor.visible = false;
   942 		_cursor.visible = false;
   962 		memcpy_pitch(
   943 		blitter->CopyFromBuffer(blitter->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);
   963 			_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
       
   964 			_cursor_backup,
       
   965 			_cursor.draw_size.x, _cursor.draw_size.y, _cursor.draw_size.x, _screen.pitch);
       
   966 
       
   967 		_video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y);
   944 		_video_driver->make_dirty(_cursor.draw_pos.x, _cursor.draw_pos.y, _cursor.draw_size.x, _cursor.draw_size.y);
   968 	}
   945 	}
   969 }
   946 }
   970 
   947 
   971 void DrawMouseCursor()
   948 void DrawMouseCursor()
   972 {
   949 {
       
   950 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
   973 	int x;
   951 	int x;
   974 	int y;
   952 	int y;
   975 	int w;
   953 	int w;
   976 	int h;
   954 	int h;
   977 
   955 
  1004 	if (h > _screen.height - y) h = _screen.height - y;
   982 	if (h > _screen.height - y) h = _screen.height - y;
  1005 	if (h <= 0) return;
   983 	if (h <= 0) return;
  1006 	_cursor.draw_pos.y = y;
   984 	_cursor.draw_pos.y = y;
  1007 	_cursor.draw_size.y = h;
   985 	_cursor.draw_size.y = h;
  1008 
   986 
  1009 	assert(w * h < (int)sizeof(_cursor_backup));
   987 	assert(blitter->BufferSize(w, h) < (int)sizeof(_cursor_backup));
  1010 
   988 
  1011 	/* Make backup of stuff below cursor */
   989 	/* Make backup of stuff below cursor */
  1012 	memcpy_pitch(
   990 	blitter->CopyToBuffer(blitter->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);
  1013 		_cursor_backup,
       
  1014 		_screen.dst_ptr + _cursor.draw_pos.x + _cursor.draw_pos.y * _screen.pitch,
       
  1015 		_cursor.draw_size.x, _cursor.draw_size.y, _screen.pitch, _cursor.draw_size.x);
       
  1016 
   991 
  1017 	/* Draw cursor on screen */
   992 	/* Draw cursor on screen */
  1018 	_cur_dpi = &_screen;
   993 	_cur_dpi = &_screen;
  1019 	DrawSprite(_cursor.sprite, _cursor.pal, _cursor.pos.x, _cursor.pos.y);
   994 	DrawSprite(_cursor.sprite, _cursor.pal, _cursor.pos.x, _cursor.pos.y);
  1020 
   995 
  1200  * @return return false if the requested rectangle is not possible with the
  1175  * @return return false if the requested rectangle is not possible with the
  1201  * current dpi pointer. Only continue of the return value is true, or you'll
  1176  * current dpi pointer. Only continue of the return value is true, or you'll
  1202  * get some nasty results */
  1177  * get some nasty results */
  1203 bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
  1178 bool FillDrawPixelInfo(DrawPixelInfo *n, int left, int top, int width, int height)
  1204 {
  1179 {
       
  1180 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
  1205 	const DrawPixelInfo *o = _cur_dpi;
  1181 	const DrawPixelInfo *o = _cur_dpi;
  1206 
  1182 
  1207 	n->zoom = ZOOM_LVL_NORMAL;
  1183 	n->zoom = ZOOM_LVL_NORMAL;
  1208 
  1184 
  1209 	assert(width > 0);
  1185 	assert(width > 0);
  1231 		top = 0;
  1207 		top = 0;
  1232 	} else {
  1208 	} else {
  1233 		n->top = 0;
  1209 		n->top = 0;
  1234 	}
  1210 	}
  1235 
  1211 
  1236 	n->dst_ptr = o->dst_ptr + left + top * (n->pitch = o->pitch);
  1212 	n->dst_ptr = blitter->MoveTo(o->dst_ptr, left, top);
       
  1213 	n->pitch = o->pitch;
  1237 
  1214 
  1238 	if (height > o->height - top) {
  1215 	if (height > o->height - top) {
  1239 		height = o->height - top;
  1216 		height = o->height - top;
  1240 		if (height <= 0) return false;
  1217 		if (height <= 0) return false;
  1241 	}
  1218 	}