diff src/gb/gbGfx.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/gb/gbGfx.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,552 @@
     1.4 +#include <cstring>
     1.5 +
     1.6 +#include "gbGlobals.h"
     1.7 +#include "gbSGB.h"
     1.8 +
     1.9 +extern int32 layerSettings;
    1.10 +
    1.11 +u8 gbInvertTab[256] = {
    1.12 +	0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
    1.13 +	0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
    1.14 +	0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
    1.15 +	0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
    1.16 +	0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
    1.17 +	0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
    1.18 +	0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
    1.19 +	0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
    1.20 +	0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
    1.21 +	0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
    1.22 +	0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
    1.23 +	0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
    1.24 +	0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
    1.25 +	0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
    1.26 +	0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
    1.27 +	0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
    1.28 +	0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
    1.29 +	0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
    1.30 +	0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
    1.31 +	0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
    1.32 +	0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
    1.33 +	0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
    1.34 +	0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
    1.35 +	0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
    1.36 +	0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
    1.37 +	0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
    1.38 +	0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
    1.39 +	0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
    1.40 +	0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
    1.41 +	0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
    1.42 +	0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
    1.43 +	0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
    1.44 +};
    1.45 +
    1.46 +u16 gbLineMix[160];
    1.47 +
    1.48 +void gbRenderLine()
    1.49 +{
    1.50 +	u8 *bank0;
    1.51 +	u8 *bank1;
    1.52 +	if (gbCgbMode)
    1.53 +	{
    1.54 +		bank0 = &gbVram[0x0000];
    1.55 +		bank1 = &gbVram[0x2000];
    1.56 +	}
    1.57 +	else
    1.58 +	{
    1.59 +		bank0 = &gbMemory[0x8000];
    1.60 +		bank1 = NULL;
    1.61 +	}
    1.62 +
    1.63 +	int tile_map = 0x1800;
    1.64 +	if ((register_LCDC & 8) != 0)
    1.65 +		tile_map = 0x1c00;
    1.66 +
    1.67 +	int tile_pattern = 0x0800;
    1.68 +
    1.69 +	if ((register_LCDC & 16) != 0)
    1.70 +		tile_pattern = 0x0000;
    1.71 +
    1.72 +	int x = 0;
    1.73 +	int y = register_LY;
    1.74 +
    1.75 +	if (y >= 144)
    1.76 +		return;
    1.77 +
    1.78 +	//  int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip;
    1.79 +
    1.80 +	int sx = register_SCX;
    1.81 +	int sy = register_SCY;
    1.82 +
    1.83 +	sy += y;
    1.84 +
    1.85 +	sy &= 255;
    1.86 +
    1.87 +	int tx = sx >> 3;
    1.88 +	int ty = sy >> 3;
    1.89 +
    1.90 +	int bx = 1 << (7 - (sx & 7));
    1.91 +	int by = sy & 7;
    1.92 +
    1.93 +	int tile_map_line_y = tile_map + ty * 32;
    1.94 +
    1.95 +	int tile_map_address = tile_map_line_y + tx;
    1.96 +
    1.97 +	u8 attrs = 0;
    1.98 +	if (bank1 != NULL)
    1.99 +		attrs = bank1[tile_map_address];
   1.100 +
   1.101 +	u8 tile = bank0[tile_map_address];
   1.102 +
   1.103 +	tile_map_address++;
   1.104 +
   1.105 +	if ((register_LCDC & 16) == 0)
   1.106 +	{
   1.107 +		if (tile < 128)
   1.108 +			tile += 128;
   1.109 +		else
   1.110 +			tile -= 128;
   1.111 +	}
   1.112 +
   1.113 +	int tile_pattern_address = tile_pattern + tile * 16 + by*2;
   1.114 +
   1.115 +	if (register_LCDC & 0x80)
   1.116 +	{
   1.117 +		if ((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100))
   1.118 +		{
   1.119 +			while (x < 160)
   1.120 +			{
   1.121 +				u8 tile_a = 0;
   1.122 +				u8 tile_b = 0;
   1.123 +
   1.124 +				if (attrs & 0x40)
   1.125 +				{
   1.126 +					tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;
   1.127 +				}
   1.128 +
   1.129 +				if (attrs & 0x08)
   1.130 +				{
   1.131 +					tile_a = bank1[tile_pattern_address++];
   1.132 +					tile_b = bank1[tile_pattern_address];
   1.133 +				}
   1.134 +				else
   1.135 +				{
   1.136 +					tile_a = bank0[tile_pattern_address++];
   1.137 +					tile_b = bank0[tile_pattern_address];
   1.138 +				}
   1.139 +
   1.140 +				if (attrs & 0x20)
   1.141 +				{
   1.142 +					tile_a = gbInvertTab[tile_a];
   1.143 +					tile_b = gbInvertTab[tile_b];
   1.144 +				}
   1.145 +
   1.146 +				while (bx > 0)
   1.147 +				{
   1.148 +					u8 c = (tile_a & bx) ? 1 : 0;
   1.149 +					c += ((tile_b & bx) ? 2 : 0);
   1.150 +
   1.151 +					gbLineBuffer[x] = c; // mark the gbLineBuffer color
   1.152 +
   1.153 +					if (attrs & 0x80)
   1.154 +						gbLineBuffer[x] |= 0x300;
   1.155 +
   1.156 +					if (gbCgbMode)
   1.157 +					{
   1.158 +						c = c + (attrs & 7)*4;
   1.159 +					}
   1.160 +					else
   1.161 +					{
   1.162 +						c = gbBgp[c];
   1.163 +						if (gbSgbMode && !gbCgbMode)
   1.164 +						{
   1.165 +							int dx = x >> 3;
   1.166 +							int dy = y >> 3;
   1.167 +
   1.168 +							int palette = gbSgbATF[dy * 20 + dx];
   1.169 +
   1.170 +							if (c == 0)
   1.171 +								palette = 0;
   1.172 +
   1.173 +							c = c + 4*palette;
   1.174 +						}
   1.175 +					}
   1.176 +					gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
   1.177 +					               gbPalette[c];
   1.178 +					x++;
   1.179 +					if (x >= 160)
   1.180 +						break;
   1.181 +					bx >>= 1;
   1.182 +				}
   1.183 +				tx++;
   1.184 +				if (tx == 32)
   1.185 +					tx = 0;
   1.186 +				bx = 128;
   1.187 +
   1.188 +				if (bank1)
   1.189 +					attrs = bank1[tile_map_line_y + tx];
   1.190 +
   1.191 +				tile = bank0[tile_map_line_y + tx];
   1.192 +
   1.193 +				if ((register_LCDC & 16) == 0)
   1.194 +				{
   1.195 +					if (tile < 128)
   1.196 +						tile += 128;
   1.197 +					else
   1.198 +						tile -= 128;
   1.199 +				}
   1.200 +				tile_pattern_address = tile_pattern + tile * 16 + by * 2;
   1.201 +			}
   1.202 +		}
   1.203 +		else
   1.204 +		{
   1.205 +			for (int i = 0; i < 160; i++)
   1.206 +			{
   1.207 +				gbLineMix[i]    = gbPalette[0];
   1.208 +				gbLineBuffer[i] = 0;
   1.209 +			}
   1.210 +		}
   1.211 +
   1.212 +		// do the window display
   1.213 +		if ((register_LCDC & 0x20) && (layerSettings & 0x2000))
   1.214 +		{
   1.215 +			int wy = register_WY;
   1.216 +
   1.217 +			if (y >= wy)
   1.218 +			{
   1.219 +				int wx = register_WX;
   1.220 +				wx -= 7;
   1.221 +
   1.222 +				if (wx <= 159 && gbWindowLine <= 143)
   1.223 +				{
   1.224 +					tile_map = 0x1800;
   1.225 +
   1.226 +					if ((register_LCDC & 0x40) != 0)
   1.227 +						tile_map = 0x1c00;
   1.228 +
   1.229 +					if (gbWindowLine == -1)
   1.230 +					{
   1.231 +						gbWindowLine = 0;
   1.232 +					}
   1.233 +
   1.234 +					tx = 0;
   1.235 +					ty = gbWindowLine >> 3;
   1.236 +
   1.237 +					bx = 128;
   1.238 +					by = gbWindowLine & 7;
   1.239 +
   1.240 +					if (wx < 0)
   1.241 +					{
   1.242 +						bx >>= (-wx);
   1.243 +						wx   = 0;
   1.244 +					}
   1.245 +
   1.246 +					tile_map_line_y = tile_map + ty * 32;
   1.247 +
   1.248 +					tile_map_address = tile_map_line_y + tx;
   1.249 +
   1.250 +					x = wx;
   1.251 +
   1.252 +					tile = bank0[tile_map_address];
   1.253 +					u8 attrs = 0;
   1.254 +					if (bank1)
   1.255 +						attrs = bank1[tile_map_address];
   1.256 +					tile_map_address++;
   1.257 +
   1.258 +					if ((register_LCDC & 16) == 0)
   1.259 +					{
   1.260 +						if (tile < 128)
   1.261 +							tile += 128;
   1.262 +						else
   1.263 +							tile -= 128;
   1.264 +					}
   1.265 +
   1.266 +					tile_pattern_address = tile_pattern + tile * 16 + by*2;
   1.267 +
   1.268 +					while (x < 160)
   1.269 +					{
   1.270 +						u8 tile_a = 0;
   1.271 +						u8 tile_b = 0;
   1.272 +
   1.273 +						if (attrs & 0x40)
   1.274 +						{
   1.275 +							tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;
   1.276 +						}
   1.277 +
   1.278 +						if (attrs & 0x08)
   1.279 +						{
   1.280 +							tile_a = bank1[tile_pattern_address++];
   1.281 +							tile_b = bank1[tile_pattern_address];
   1.282 +						}
   1.283 +						else
   1.284 +						{
   1.285 +							tile_a = bank0[tile_pattern_address++];
   1.286 +							tile_b = bank0[tile_pattern_address];
   1.287 +						}
   1.288 +
   1.289 +						if (attrs & 0x20)
   1.290 +						{
   1.291 +							tile_a = gbInvertTab[tile_a];
   1.292 +							tile_b = gbInvertTab[tile_b];
   1.293 +						}
   1.294 +
   1.295 +						while (bx > 0)
   1.296 +						{
   1.297 +							u8 c = (tile_a & bx) != 0 ? 1 : 0;
   1.298 +							c += ((tile_b & bx) != 0 ? 2 : 0);
   1.299 +
   1.300 +							if (attrs & 0x80)
   1.301 +								gbLineBuffer[x] = 0x300 + c;
   1.302 +							else
   1.303 +								gbLineBuffer[x] = 0x100 + c;
   1.304 +
   1.305 +							if (gbCgbMode)
   1.306 +							{
   1.307 +								c = c + (attrs & 7) * 4;
   1.308 +							}
   1.309 +							else
   1.310 +							{
   1.311 +								c = gbBgp[c];
   1.312 +								if (gbSgbMode && !gbCgbMode)
   1.313 +								{
   1.314 +									int dx = x >> 3;
   1.315 +									int dy = y >> 3;
   1.316 +
   1.317 +									int palette = gbSgbATF[dy * 20 + dx];
   1.318 +
   1.319 +									if (c == 0)
   1.320 +										palette = 0;
   1.321 +
   1.322 +									c = c + 4*palette;
   1.323 +								}
   1.324 +							}
   1.325 +							gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :
   1.326 +							               gbPalette[c];
   1.327 +							x++;
   1.328 +							if (x >= 160)
   1.329 +								break;
   1.330 +							bx >>= 1;
   1.331 +						}
   1.332 +						tx++;
   1.333 +						if (tx == 32)
   1.334 +							tx = 0;
   1.335 +						bx   = 128;
   1.336 +						tile = bank0[tile_map_line_y + tx];
   1.337 +						if (bank1)
   1.338 +							attrs = bank1[tile_map_line_y + tx];
   1.339 +
   1.340 +						if ((register_LCDC & 16) == 0)
   1.341 +						{
   1.342 +							if (tile < 128)
   1.343 +								tile += 128;
   1.344 +							else
   1.345 +								tile -= 128;
   1.346 +						}
   1.347 +						tile_pattern_address = tile_pattern + tile * 16 + by * 2;
   1.348 +					}
   1.349 +					gbWindowLine++;
   1.350 +				}
   1.351 +			}
   1.352 +		}
   1.353 +	}
   1.354 +	else
   1.355 +	{
   1.356 +		for (int i = 0; i < 160; i++)
   1.357 +		{
   1.358 +			gbLineMix[i]    = gbPalette[0];
   1.359 +			gbLineBuffer[i] = 0;
   1.360 +		}
   1.361 +	}
   1.362 +}
   1.363 +
   1.364 +void gbDrawSpriteTile(int tile, int x, int y, int t, int flags,
   1.365 +                      int size, int spriteNumber)
   1.366 +{
   1.367 +	u8 *bank0;
   1.368 +	u8 *bank1;
   1.369 +	if (gbCgbMode)
   1.370 +	{
   1.371 +		if (register_VBK & 1)
   1.372 +		{
   1.373 +			bank0 = &gbVram[0x0000];
   1.374 +			bank1 = &gbVram[0x2000];
   1.375 +		}
   1.376 +		else
   1.377 +		{
   1.378 +			bank0 = &gbVram[0x0000];
   1.379 +			bank1 = &gbVram[0x2000];
   1.380 +		}
   1.381 +	}
   1.382 +	else
   1.383 +	{
   1.384 +		bank0 = &gbMemory[0x8000];
   1.385 +		bank1 = NULL;
   1.386 +	}
   1.387 +
   1.388 +	int init = 0x0000;
   1.389 +
   1.390 +	//  int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip;
   1.391 +
   1.392 +	u8 *pal = gbObp0;
   1.393 +
   1.394 +	int flipx = (flags & 0x20);
   1.395 +	int flipy = (flags & 0x40);
   1.396 +
   1.397 +	if ((flags & 0x10))
   1.398 +		pal = gbObp1;
   1.399 +
   1.400 +	if (flipy)
   1.401 +	{
   1.402 +		t = (size ? 15 : 7) - t;
   1.403 +	}
   1.404 +
   1.405 +	int prio =  flags & 0x80;
   1.406 +
   1.407 +	int address = init + tile * 16 + 2*t;
   1.408 +	int a       = 0;
   1.409 +	int b       = 0;
   1.410 +
   1.411 +	if (gbCgbMode && flags & 0x08)
   1.412 +	{
   1.413 +		a = bank1[address++];
   1.414 +		b = bank1[address++];
   1.415 +	}
   1.416 +	else
   1.417 +	{
   1.418 +		a = bank0[address++];
   1.419 +		b = bank0[address++];
   1.420 +	}
   1.421 +
   1.422 +	for (int xx = 0; xx < 8; xx++)
   1.423 +	{
   1.424 +		u8 mask = 1 << (7-xx);
   1.425 +		u8 c    = 0;
   1.426 +		if ((a & mask))
   1.427 +			c++;
   1.428 +		if ((b & mask))
   1.429 +			c += 2;
   1.430 +
   1.431 +		if (c == 0)
   1.432 +			continue;
   1.433 +
   1.434 +		int xxx = xx+x;
   1.435 +		if (flipx)
   1.436 +			xxx = (7-xx+x);
   1.437 +
   1.438 +		if (xxx < 0 || xxx > 159)
   1.439 +			continue;
   1.440 +
   1.441 +		u16 color = gbLineBuffer[xxx];
   1.442 +
   1.443 +		if (prio)
   1.444 +		{
   1.445 +			if (color < 0x200 && ((color & 0xFF) != 0))
   1.446 +				continue;
   1.447 +		}
   1.448 +		if (color >= 0x300 && color != 0x300)
   1.449 +			continue;
   1.450 +		else if (color >= 0x200 && color < 0x300)
   1.451 +		{
   1.452 +			int sprite = color & 0xff;
   1.453 +
   1.454 +			int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8;
   1.455 +
   1.456 +			if (spriteX == x)
   1.457 +			{
   1.458 +				if (sprite < spriteNumber)
   1.459 +					continue;
   1.460 +			}
   1.461 +			else
   1.462 +			{
   1.463 +				if (gbCgbMode)
   1.464 +				{
   1.465 +					if (sprite < spriteNumber)
   1.466 +						continue;
   1.467 +				}
   1.468 +				else
   1.469 +				{
   1.470 +					if (spriteX < x+8)
   1.471 +						continue;
   1.472 +				}
   1.473 +			}
   1.474 +		}
   1.475 +
   1.476 +		gbLineBuffer[xxx] = 0x200 + spriteNumber;
   1.477 +
   1.478 +		// make sure that sprites will work even in CGB mode
   1.479 +		if (gbCgbMode)
   1.480 +		{
   1.481 +			c = c + (flags & 0x07)*4 + 32;
   1.482 +		}
   1.483 +		else
   1.484 +		{
   1.485 +			c = pal[c];
   1.486 +
   1.487 +			if (gbSgbMode && !gbCgbMode)
   1.488 +			{
   1.489 +				int dx = xxx >> 3;
   1.490 +				int dy = y >> 3;
   1.491 +
   1.492 +				int palette = gbSgbATF[dy * 20 + dx];
   1.493 +
   1.494 +				if (c == 0)
   1.495 +					palette = 0;
   1.496 +
   1.497 +				c = c + 4*palette;
   1.498 +			}
   1.499 +			else
   1.500 +			{
   1.501 +				c += 4;
   1.502 +			}
   1.503 +		}
   1.504 +
   1.505 +		gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] :
   1.506 +		                 gbPalette[c];
   1.507 +	}
   1.508 +}
   1.509 +
   1.510 +void gbDrawSprites()
   1.511 +{
   1.512 +	int x     = 0;
   1.513 +	int y     = 0;
   1.514 +	int count = 0;
   1.515 +
   1.516 +	int size = (register_LCDC & 4);
   1.517 +
   1.518 +	if (!(register_LCDC & 0x80))
   1.519 +		return;
   1.520 +
   1.521 +	if ((register_LCDC & 2) && (layerSettings & 0x1000))
   1.522 +	{
   1.523 +		int yc = register_LY;
   1.524 +
   1.525 +		int address = 0xfe00;
   1.526 +		for (int i = 0; i < 40; i++)
   1.527 +		{
   1.528 +			y = gbMemory[address++];
   1.529 +			x = gbMemory[address++];
   1.530 +			int tile = gbMemory[address++];
   1.531 +			if (size)
   1.532 +				tile &= 254;
   1.533 +			int flags = gbMemory[address++];
   1.534 +
   1.535 +			if (x > 0 && y > 0 && x < 168 && y < 160)
   1.536 +			{
   1.537 +				// check if sprite intersects current line
   1.538 +				int t = yc -y + 16;
   1.539 +				if (size && t >= 0 && t < 16)
   1.540 +				{
   1.541 +					gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i);
   1.542 +					count++;
   1.543 +				}
   1.544 +				else if (!size && t >= 0 && t < 8)
   1.545 +				{
   1.546 +					gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i);
   1.547 +					count++;
   1.548 +				}
   1.549 +			}
   1.550 +			// sprite limit reached!
   1.551 +			if (count >= 10)
   1.552 +				break;
   1.553 +		}
   1.554 +	}
   1.555 +}