Mercurial > vba-clojure
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 +}