Mercurial > vba-clojure
view src/gb/gbGfx.cpp @ 574:be6f46094ad0
implemented video-memory pointer logic.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 01 Sep 2012 04:05:51 -0500 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #include <cstring>3 #include "gbGlobals.h"4 #include "gbSGB.h"6 extern int32 layerSettings;8 u8 gbInvertTab[256] = {9 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,10 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,11 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,12 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,13 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,14 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,15 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,16 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,17 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,18 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,19 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,20 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,21 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,22 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,23 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,24 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,25 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,26 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,27 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,28 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,29 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,30 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,31 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,32 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,33 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,34 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,35 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,36 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,37 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,38 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,39 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,40 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff41 };43 u16 gbLineMix[160];45 void gbRenderLine()46 {47 u8 *bank0;48 u8 *bank1;49 if (gbCgbMode)50 {51 bank0 = &gbVram[0x0000];52 bank1 = &gbVram[0x2000];53 }54 else55 {56 bank0 = &gbMemory[0x8000];57 bank1 = NULL;58 }60 int tile_map = 0x1800;61 if ((register_LCDC & 8) != 0)62 tile_map = 0x1c00;64 int tile_pattern = 0x0800;66 if ((register_LCDC & 16) != 0)67 tile_pattern = 0x0000;69 int x = 0;70 int y = register_LY;72 if (y >= 144)73 return;75 // int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip;77 int sx = register_SCX;78 int sy = register_SCY;80 sy += y;82 sy &= 255;84 int tx = sx >> 3;85 int ty = sy >> 3;87 int bx = 1 << (7 - (sx & 7));88 int by = sy & 7;90 int tile_map_line_y = tile_map + ty * 32;92 int tile_map_address = tile_map_line_y + tx;94 u8 attrs = 0;95 if (bank1 != NULL)96 attrs = bank1[tile_map_address];98 u8 tile = bank0[tile_map_address];100 tile_map_address++;102 if ((register_LCDC & 16) == 0)103 {104 if (tile < 128)105 tile += 128;106 else107 tile -= 128;108 }110 int tile_pattern_address = tile_pattern + tile * 16 + by*2;112 if (register_LCDC & 0x80)113 {114 if ((register_LCDC & 0x01 || gbCgbMode) && (layerSettings & 0x0100))115 {116 while (x < 160)117 {118 u8 tile_a = 0;119 u8 tile_b = 0;121 if (attrs & 0x40)122 {123 tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;124 }126 if (attrs & 0x08)127 {128 tile_a = bank1[tile_pattern_address++];129 tile_b = bank1[tile_pattern_address];130 }131 else132 {133 tile_a = bank0[tile_pattern_address++];134 tile_b = bank0[tile_pattern_address];135 }137 if (attrs & 0x20)138 {139 tile_a = gbInvertTab[tile_a];140 tile_b = gbInvertTab[tile_b];141 }143 while (bx > 0)144 {145 u8 c = (tile_a & bx) ? 1 : 0;146 c += ((tile_b & bx) ? 2 : 0);148 gbLineBuffer[x] = c; // mark the gbLineBuffer color150 if (attrs & 0x80)151 gbLineBuffer[x] |= 0x300;153 if (gbCgbMode)154 {155 c = c + (attrs & 7)*4;156 }157 else158 {159 c = gbBgp[c];160 if (gbSgbMode && !gbCgbMode)161 {162 int dx = x >> 3;163 int dy = y >> 3;165 int palette = gbSgbATF[dy * 20 + dx];167 if (c == 0)168 palette = 0;170 c = c + 4*palette;171 }172 }173 gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :174 gbPalette[c];175 x++;176 if (x >= 160)177 break;178 bx >>= 1;179 }180 tx++;181 if (tx == 32)182 tx = 0;183 bx = 128;185 if (bank1)186 attrs = bank1[tile_map_line_y + tx];188 tile = bank0[tile_map_line_y + tx];190 if ((register_LCDC & 16) == 0)191 {192 if (tile < 128)193 tile += 128;194 else195 tile -= 128;196 }197 tile_pattern_address = tile_pattern + tile * 16 + by * 2;198 }199 }200 else201 {202 for (int i = 0; i < 160; i++)203 {204 gbLineMix[i] = gbPalette[0];205 gbLineBuffer[i] = 0;206 }207 }209 // do the window display210 if ((register_LCDC & 0x20) && (layerSettings & 0x2000))211 {212 int wy = register_WY;214 if (y >= wy)215 {216 int wx = register_WX;217 wx -= 7;219 if (wx <= 159 && gbWindowLine <= 143)220 {221 tile_map = 0x1800;223 if ((register_LCDC & 0x40) != 0)224 tile_map = 0x1c00;226 if (gbWindowLine == -1)227 {228 gbWindowLine = 0;229 }231 tx = 0;232 ty = gbWindowLine >> 3;234 bx = 128;235 by = gbWindowLine & 7;237 if (wx < 0)238 {239 bx >>= (-wx);240 wx = 0;241 }243 tile_map_line_y = tile_map + ty * 32;245 tile_map_address = tile_map_line_y + tx;247 x = wx;249 tile = bank0[tile_map_address];250 u8 attrs = 0;251 if (bank1)252 attrs = bank1[tile_map_address];253 tile_map_address++;255 if ((register_LCDC & 16) == 0)256 {257 if (tile < 128)258 tile += 128;259 else260 tile -= 128;261 }263 tile_pattern_address = tile_pattern + tile * 16 + by*2;265 while (x < 160)266 {267 u8 tile_a = 0;268 u8 tile_b = 0;270 if (attrs & 0x40)271 {272 tile_pattern_address = tile_pattern + tile * 16 + (7-by)*2;273 }275 if (attrs & 0x08)276 {277 tile_a = bank1[tile_pattern_address++];278 tile_b = bank1[tile_pattern_address];279 }280 else281 {282 tile_a = bank0[tile_pattern_address++];283 tile_b = bank0[tile_pattern_address];284 }286 if (attrs & 0x20)287 {288 tile_a = gbInvertTab[tile_a];289 tile_b = gbInvertTab[tile_b];290 }292 while (bx > 0)293 {294 u8 c = (tile_a & bx) != 0 ? 1 : 0;295 c += ((tile_b & bx) != 0 ? 2 : 0);297 if (attrs & 0x80)298 gbLineBuffer[x] = 0x300 + c;299 else300 gbLineBuffer[x] = 0x100 + c;302 if (gbCgbMode)303 {304 c = c + (attrs & 7) * 4;305 }306 else307 {308 c = gbBgp[c];309 if (gbSgbMode && !gbCgbMode)310 {311 int dx = x >> 3;312 int dy = y >> 3;314 int palette = gbSgbATF[dy * 20 + dx];316 if (c == 0)317 palette = 0;319 c = c + 4*palette;320 }321 }322 gbLineMix[x] = gbColorOption ? gbColorFilter[gbPalette[c]] :323 gbPalette[c];324 x++;325 if (x >= 160)326 break;327 bx >>= 1;328 }329 tx++;330 if (tx == 32)331 tx = 0;332 bx = 128;333 tile = bank0[tile_map_line_y + tx];334 if (bank1)335 attrs = bank1[tile_map_line_y + tx];337 if ((register_LCDC & 16) == 0)338 {339 if (tile < 128)340 tile += 128;341 else342 tile -= 128;343 }344 tile_pattern_address = tile_pattern + tile * 16 + by * 2;345 }346 gbWindowLine++;347 }348 }349 }350 }351 else352 {353 for (int i = 0; i < 160; i++)354 {355 gbLineMix[i] = gbPalette[0];356 gbLineBuffer[i] = 0;357 }358 }359 }361 void gbDrawSpriteTile(int tile, int x, int y, int t, int flags,362 int size, int spriteNumber)363 {364 u8 *bank0;365 u8 *bank1;366 if (gbCgbMode)367 {368 if (register_VBK & 1)369 {370 bank0 = &gbVram[0x0000];371 bank1 = &gbVram[0x2000];372 }373 else374 {375 bank0 = &gbVram[0x0000];376 bank1 = &gbVram[0x2000];377 }378 }379 else380 {381 bank0 = &gbMemory[0x8000];382 bank1 = NULL;383 }385 int init = 0x0000;387 // int yLine = (y+gbBorderRowSkip) * gbBorderLineSkip;389 u8 *pal = gbObp0;391 int flipx = (flags & 0x20);392 int flipy = (flags & 0x40);394 if ((flags & 0x10))395 pal = gbObp1;397 if (flipy)398 {399 t = (size ? 15 : 7) - t;400 }402 int prio = flags & 0x80;404 int address = init + tile * 16 + 2*t;405 int a = 0;406 int b = 0;408 if (gbCgbMode && flags & 0x08)409 {410 a = bank1[address++];411 b = bank1[address++];412 }413 else414 {415 a = bank0[address++];416 b = bank0[address++];417 }419 for (int xx = 0; xx < 8; xx++)420 {421 u8 mask = 1 << (7-xx);422 u8 c = 0;423 if ((a & mask))424 c++;425 if ((b & mask))426 c += 2;428 if (c == 0)429 continue;431 int xxx = xx+x;432 if (flipx)433 xxx = (7-xx+x);435 if (xxx < 0 || xxx > 159)436 continue;438 u16 color = gbLineBuffer[xxx];440 if (prio)441 {442 if (color < 0x200 && ((color & 0xFF) != 0))443 continue;444 }445 if (color >= 0x300 && color != 0x300)446 continue;447 else if (color >= 0x200 && color < 0x300)448 {449 int sprite = color & 0xff;451 int spriteX = gbMemory[0xfe00 + 4 * sprite + 1] - 8;453 if (spriteX == x)454 {455 if (sprite < spriteNumber)456 continue;457 }458 else459 {460 if (gbCgbMode)461 {462 if (sprite < spriteNumber)463 continue;464 }465 else466 {467 if (spriteX < x+8)468 continue;469 }470 }471 }473 gbLineBuffer[xxx] = 0x200 + spriteNumber;475 // make sure that sprites will work even in CGB mode476 if (gbCgbMode)477 {478 c = c + (flags & 0x07)*4 + 32;479 }480 else481 {482 c = pal[c];484 if (gbSgbMode && !gbCgbMode)485 {486 int dx = xxx >> 3;487 int dy = y >> 3;489 int palette = gbSgbATF[dy * 20 + dx];491 if (c == 0)492 palette = 0;494 c = c + 4*palette;495 }496 else497 {498 c += 4;499 }500 }502 gbLineMix[xxx] = gbColorOption ? gbColorFilter[gbPalette[c]] :503 gbPalette[c];504 }505 }507 void gbDrawSprites()508 {509 int x = 0;510 int y = 0;511 int count = 0;513 int size = (register_LCDC & 4);515 if (!(register_LCDC & 0x80))516 return;518 if ((register_LCDC & 2) && (layerSettings & 0x1000))519 {520 int yc = register_LY;522 int address = 0xfe00;523 for (int i = 0; i < 40; i++)524 {525 y = gbMemory[address++];526 x = gbMemory[address++];527 int tile = gbMemory[address++];528 if (size)529 tile &= 254;530 int flags = gbMemory[address++];532 if (x > 0 && y > 0 && x < 168 && y < 160)533 {534 // check if sprite intersects current line535 int t = yc -y + 16;536 if (size && t >= 0 && t < 16)537 {538 gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i);539 count++;540 }541 else if (!size && t >= 0 && t < 8)542 {543 gbDrawSpriteTile(tile, x-8, yc, t, flags, size, i);544 count++;545 }546 }547 // sprite limit reached!548 if (count >= 10)549 break;550 }551 }552 }