src/gfx.cpp
branchgamebalance
changeset 9912 1ac8aac92385
parent 9911 0b8b245a2391
child 9913 e79cd19772dd
equal deleted inserted replaced
9911:0b8b245a2391 9912:1ac8aac92385
    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 
    23 
    23 #ifdef _DEBUG
    24 #ifdef _DEBUG
    24 bool _dbg_screen_rect;
    25 bool _dbg_screen_rect;
    25 #endif
    26 #endif
    26 
    27 
    42 int _pal_first_dirty;
    43 int _pal_first_dirty;
    43 int _pal_last_dirty;
    44 int _pal_last_dirty;
    44 
    45 
    45 Colour _cur_palette[256];
    46 Colour _cur_palette[256];
    46 byte _stringwidth_table[FS_END][224];
    47 byte _stringwidth_table[FS_END][224];
    47 
       
    48 enum BlitterMode {
       
    49 	BM_NORMAL,
       
    50 	BM_COLOUR_REMAP,
       
    51 	BM_TRANSPARENT,
       
    52 };
       
    53 
    48 
    54 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);
    55 
    50 
    56 FontSize _cur_fontsize;
    51 FontSize _cur_fontsize;
    57 static FontSize _last_fontsize;
    52 static FontSize _last_fontsize;
   726 	} else {
   721 	} else {
   727 		GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL);
   722 		GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL);
   728 	}
   723 	}
   729 }
   724 }
   730 
   725 
   731 struct BlitterParams {
   726 static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
   732 	int start_x, start_y;
       
   733 	const byte *sprite;
       
   734 	Pixel *dst;
       
   735 	BlitterMode mode;
       
   736 	int width, height;
       
   737 	int width_org;
       
   738 	int pitch;
       
   739 };
       
   740 
       
   741 static void GfxBlitZoomUncomp(BlitterParams *bp, ZoomLevel zoom)
       
   742 {
       
   743 	const byte *src = bp->sprite;
       
   744 	Pixel *dst = bp->dst;
       
   745 	int height = bp->height;
       
   746 	int width = bp->width;
       
   747 	int i;
       
   748 
       
   749 	assert(height > 0);
       
   750 	assert(width > 0);
       
   751 
       
   752 	height = UnScaleByZoom(height, zoom);
       
   753 
       
   754 	switch (bp->mode) {
       
   755 		case BM_COLOUR_REMAP: {
       
   756 			const byte *ctab = _color_remap_ptr;
       
   757 
       
   758 			for (; height != 0; height--) {
       
   759 				for (i = 0; i != UnScaleByZoom(width, zoom); i++) {
       
   760 					byte b = ctab[src[ScaleByZoom(i, zoom)]];
       
   761 
       
   762 					if (b != 0) dst[i] = b;
       
   763 				}
       
   764 				src += ScaleByZoom(bp->width_org, zoom);
       
   765 				dst += bp->pitch;
       
   766 			}
       
   767 			break;
       
   768 		}
       
   769 
       
   770 		case BM_TRANSPARENT: {
       
   771 			const byte *ctab = _color_remap_ptr;
       
   772 
       
   773 			for (; height != 0; height--) {
       
   774 				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
       
   775 					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = ctab[dst[i]];
       
   776 				src += ScaleByZoom(bp->width_org, zoom);
       
   777 				dst += bp->pitch;
       
   778 			}
       
   779 			break;
       
   780 		}
       
   781 
       
   782 		default:
       
   783 			for (; height != 0; height--) {
       
   784 				for (i = 0; i != UnScaleByZoom(width, zoom); i++)
       
   785 					if (src[ScaleByZoom(i, zoom)] != 0) dst[i] = src[ScaleByZoom(i, zoom)];
       
   786 				src += ScaleByZoom(bp->width_org, zoom);
       
   787 				dst += bp->pitch;
       
   788 			}
       
   789 			break;
       
   790 	}
       
   791 }
       
   792 
       
   793 static void GfxBlitTileZoom(BlitterParams *bp, ZoomLevel zoom)
       
   794 {
       
   795 	const byte *src_o = bp->sprite;
       
   796 	const byte *src;
       
   797 	int num, skip;
       
   798 	byte done;
       
   799 	Pixel *dst;
       
   800 	const byte *ctab;
       
   801 
       
   802 	src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
       
   803 
       
   804 	for (;;) {
       
   805 		do {
       
   806 			done = src_o[0];
       
   807 			num = done & 0x7F;
       
   808 			skip = src_o[1];
       
   809 			src = src_o + 2;
       
   810 			src_o += num + 2;
       
   811 
       
   812 			dst = bp->dst;
       
   813 
       
   814 			if (zoom >= ZOOM_LVL_OUT_2X && (skip & 1)) {
       
   815 				skip += 1;
       
   816 				src += 1;
       
   817 				num -= 1;
       
   818 				if (num <= 0) continue;
       
   819 			}
       
   820 
       
   821 			if (zoom >= ZOOM_LVL_OUT_4X && (skip & 2)) {
       
   822 				skip += 2;
       
   823 				src += 2;
       
   824 				num -= 2;
       
   825 				if (num <= 0) continue;
       
   826 			}
       
   827 
       
   828 			if (zoom >= ZOOM_LVL_OUT_8X && (skip & 4)) {
       
   829 				skip += 4;
       
   830 				src += 4;
       
   831 				num -= 4;
       
   832 				if (num <= 0) continue;
       
   833 			}
       
   834 
       
   835 			if (zoom >= ZOOM_LVL_OUT_16X && (skip & 8)) {
       
   836 				skip += 8;
       
   837 				src += 8;
       
   838 				num -= 8;
       
   839 				if (num <= 0) continue;
       
   840 			}
       
   841 
       
   842 			if ( (skip -= bp->start_x) > 0) {
       
   843 				dst += UnScaleByZoom(skip, zoom);
       
   844 			} else {
       
   845 				src -= skip;
       
   846 				num += skip;
       
   847 				if (num <= 0) continue;
       
   848 				skip = 0;
       
   849 			}
       
   850 
       
   851 			skip = skip + num - bp->width;
       
   852 			if (skip > 0) {
       
   853 				num -= skip;
       
   854 				if (num <= 0) continue;
       
   855 			}
       
   856 
       
   857 			num = UnScaleByZoom(num + ScaleByZoom(1, zoom) - 1, zoom);
       
   858 
       
   859 			switch (bp->mode) {
       
   860 				case BM_COLOUR_REMAP:
       
   861 					ctab = _color_remap_ptr;
       
   862 					for (; num != 0; num--) {
       
   863 							*dst = ctab[*src];
       
   864 							dst++;
       
   865 							src += ScaleByZoom(1, zoom);
       
   866 					}
       
   867 					break;
       
   868 
       
   869 				case BM_TRANSPARENT:
       
   870 					ctab = _color_remap_ptr;
       
   871 					for (; num != 0; num--) {
       
   872 							*dst = ctab[*dst];
       
   873 							dst++;
       
   874 					}
       
   875 					break;
       
   876 
       
   877 				default:
       
   878 					for (; num != 0; num--) {
       
   879 							*dst = *src;
       
   880 							dst++;
       
   881 							src += ScaleByZoom(1, zoom);
       
   882 					}
       
   883 					break;
       
   884 			}
       
   885 
       
   886 
       
   887 		} while (!(done & 0x80));
       
   888 
       
   889 		bp->dst += bp->pitch;
       
   890 		if (--bp->height == 0) return;
       
   891 
       
   892 		for (int i = 0; i < ScaleByZoom(1, zoom) - 1; i++) {
       
   893 			do {
       
   894 				done = src_o[0];
       
   895 				src_o += (done & 0x7F) + 2;
       
   896 			} while (!(done & 0x80));
       
   897 			if (--bp->height == 0) return;
       
   898 		}
       
   899 	}
       
   900 }
       
   901 
       
   902 static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
       
   903 {
   727 {
   904 	const DrawPixelInfo *dpi = _cur_dpi;
   728 	const DrawPixelInfo *dpi = _cur_dpi;
   905 	int start_x, start_y;
   729 	Blitter::BlitterParams bp;
   906 	BlitterParams bp;
   730 
   907 	int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1);
   731 	/* Move to the correct offset */
   908 
       
   909 	/* decode sprite header */
       
   910 	x += sprite->x_offs;
   732 	x += sprite->x_offs;
   911 	y += sprite->y_offs;
   733 	y += sprite->y_offs;
   912 	bp.width_org = bp.width = sprite->width;
   734 
   913 	bp.height = sprite->height;
   735 	/* Copy the main data directly from the sprite */
   914 	bp.sprite = sprite->data;
   736 	bp.sprite = sprite->data;
       
   737 	bp.sprite_width = sprite->width;
       
   738 	bp.sprite_height = sprite->height;
       
   739 	bp.width = UnScaleByZoom(sprite->width, dpi->zoom);
       
   740 	bp.height = UnScaleByZoom(sprite->height, dpi->zoom);
       
   741 	bp.top = 0;
       
   742 	bp.left = 0;
       
   743 	bp.skip_left = 0;
       
   744 	bp.skip_top = 0;
   915 	bp.dst = dpi->dst_ptr;
   745 	bp.dst = dpi->dst_ptr;
   916 	bp.mode = mode;
       
   917 	bp.pitch = dpi->pitch;
   746 	bp.pitch = dpi->pitch;
   918 
   747 	bp.remap = _color_remap_ptr;
   919 	assert(bp.height > 0);
   748 
   920 	assert(bp.width > 0);
   749 	assert(sprite->width > 0);
   921 
   750 	assert(sprite->height > 0);
   922 	if (sprite->info & 8) {
   751 
   923 		/* tile blit */
   752 	if (bp.width <= 0) return;
   924 		start_y = 0;
   753 	if (bp.height <= 0) return;
   925 
   754 
   926 		if (dpi->zoom > ZOOM_LVL_NORMAL) {
   755 	y -= dpi->top;
   927 			start_y += bp.height & ~zoom_mask;
   756 	/* Check for top overflow */
   928 			bp.height &= zoom_mask;
   757 	if (y < 0) {
   929 			if (bp.height == 0) return;
   758 		bp.height -= -UnScaleByZoom(y, dpi->zoom);
   930 			y &= zoom_mask;
   759 		if (bp.height <= 0) return;
   931 		}
   760 		bp.skip_top += -UnScaleByZoom(y, dpi->zoom);
   932 
   761 		y = 0;
   933 		if ( (y -= dpi->top) < 0) {
       
   934 			bp.height += y;
       
   935 			if (bp.height <= 0) return;
       
   936 			start_y -= y;
       
   937 			y = 0;
       
   938 		} else {
       
   939 			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
       
   940 		}
       
   941 		bp.start_y = start_y;
       
   942 
       
   943 		if ( (y = y + bp.height - dpi->height) > 0) {
       
   944 			bp.height -= y;
       
   945 			if (bp.height <= 0) return;
       
   946 		}
       
   947 
       
   948 		start_x = 0;
       
   949 		x &= zoom_mask;
       
   950 		if ( (x -= dpi->left) < 0) {
       
   951 			bp.width += x;
       
   952 			if (bp.width <= 0) return;
       
   953 			start_x -= x;
       
   954 			x = 0;
       
   955 		}
       
   956 		bp.start_x = start_x;
       
   957 		bp.dst += UnScaleByZoom(x, dpi->zoom);
       
   958 
       
   959 		if ( (x = x + bp.width - dpi->width) > 0) {
       
   960 			bp.width -= x;
       
   961 			if (bp.width <= 0) return;
       
   962 		}
       
   963 
       
   964 		GfxBlitTileZoom(&bp, dpi->zoom);
       
   965 	} else {
   762 	} else {
   966 		bp.sprite += bp.width * (bp.height & ~zoom_mask);
   763 		bp.top = UnScaleByZoom(y, dpi->zoom);
   967 		bp.height &= zoom_mask;
   764 	}
   968 		if (bp.height == 0) return;
   765 
   969 
   766 	/* Check for bottom overflow */
   970 		y &= zoom_mask;
   767 	y += ScaleByZoom(bp.height, dpi->zoom) - dpi->height;
   971 
   768 	if (y > 0) {
   972 		if ( (y -= dpi->top) < 0) {
   769 		bp.height -= UnScaleByZoom(y, dpi->zoom);
   973 			bp.height += y;
   770 		if (bp.height <= 0) return;
   974 			if (bp.height <= 0) return;
   771 	}
   975 			bp.sprite -= bp.width * y;
   772 
   976 			y = 0;
   773 	x -= dpi->left;
   977 		} else {
   774 	/* Check for left overflow */
   978 			bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
   775 	if (x < 0) {
   979 		}
   776 		bp.width -= -UnScaleByZoom(x, dpi->zoom);
   980 
   777 		if (bp.width <= 0) return;
   981 		if (bp.height > dpi->height - y) {
   778 		bp.skip_left += -UnScaleByZoom(x, dpi->zoom);
   982 			bp.height = dpi->height - y;
   779 		x = 0;
   983 			if (bp.height <= 0) return;
   780 	} else {
   984 		}
   781 		bp.left = UnScaleByZoom(x, dpi->zoom);
   985 
   782 	}
   986 		x &= zoom_mask;
   783 
   987 
   784 	/* Check for right overflow */
   988 		if ( (x -= dpi->left) < 0) {
   785 	x += ScaleByZoom(bp.width, dpi->zoom) - dpi->width;
   989 			bp.width += x;
   786 	if (x > 0) {
   990 			if (bp.width <= 0) return;
   787 		bp.width -= UnScaleByZoom(x, dpi->zoom);
   991 			bp.sprite -= x;
   788 		if (bp.width <= 0) return;
   992 			x = 0;
   789 	}
   993 		}
   790 
   994 		bp.dst += UnScaleByZoom(x, dpi->zoom);
   791 	BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom);
   995 
       
   996 		if (bp.width > dpi->width - x) {
       
   997 			bp.width = dpi->width - x;
       
   998 			if (bp.width <= 0) return;
       
   999 		}
       
  1000 
       
  1001 		GfxBlitZoomUncomp(&bp, dpi->zoom);
       
  1002 	}
       
  1003 }
   792 }
  1004 
   793 
  1005 void DoPaletteAnimations();
   794 void DoPaletteAnimations();
  1006 
   795 
  1007 void GfxInitPalettes()
   796 void GfxInitPalettes()