14using namespace PpuRegisters;
20static const int kLayersPerMode[10][12] = {
21 {4, 0, 1, 4, 0, 1, 4, 2, 3, 4, 2, 3}, {4, 0, 1, 4, 0, 1, 4, 2, 4, 2, 5, 5},
22 {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
23 {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
24 {4, 0, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5}, {4, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5, 5},
25 {2, 4, 0, 1, 4, 0, 1, 4, 4, 2, 5, 5}, {4, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5, 5}};
27static const int kPrioritysPerMode[10][12] = {
28 {3, 1, 1, 2, 0, 0, 1, 1, 1, 0, 0, 0}, {3, 1, 1, 2, 0, 0, 1, 1, 0, 0, 5, 5},
29 {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
30 {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
31 {3, 1, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5}, {3, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5},
32 {1, 3, 1, 1, 2, 0, 0, 1, 0, 0, 5, 5}, {3, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5, 5}};
34static const int kLayerCountPerMode[10] = {12, 10, 8, 8, 8, 8, 6, 5, 10, 7};
36static const int kBitDepthsPerMode[10][4] = {
37 {2, 2, 2, 2}, {4, 4, 2, 5}, {4, 4, 5, 5}, {8, 4, 5, 5}, {8, 2, 5, 5},
38 {4, 2, 5, 5}, {4, 5, 5, 5}, {8, 5, 5, 5}, {4, 4, 2, 5}, {8, 7, 5, 5}};
40static const int kSpriteSizes[8][2] = {{8, 16}, {8, 32}, {8, 64}, {16, 32},
41 {16, 64}, {32, 64}, {16, 32}, {16, 32}};
56 memset(
oam, 0,
sizeof(
oam));
73 for (
int i = 0; i < 4; i++) {
87 for (
int i = 0; i < 5; i++) {
102 for (
int i = 0; i < 6; i++) {
158 for (
int x = 0; x < 256; x++) {
168 int mainLayer =
GetPixel(x, y,
false, &r, &g, &b);
183 secondLayer =
GetPixel(x, y,
true, &r2, &g2, &b2);
239 for (
int i = 0; i < kLayerCountPerMode[actMode]; i++) {
240 int curLayer = kLayersPerMode[actMode][i];
241 int curPriority = kPrioritysPerMode[actMode][i];
242 bool layerActive =
false;
292 if (
direct_color_ && layer < 4 && kBitDepthsPerMode[actMode][layer] == 8) {
293 *r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7);
294 *g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8);
295 *b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8);
297 uint16_t color =
cgram[pixel & 0xff];
299 *g = (color >> 5) & 0x1f;
300 *b = (color >> 10) & 0x1f;
302 if (layer == 4 && pixel < 0xc0)
308 uint8_t rx =
m7xFlip ? 255 - x : x;
311 bool outsideMap = xPos < 0 || xPos >= 1024 || yPos < 0 || yPos >= 1024;
315 uint8_t tile = outsideMap ? 0 :
vram[(yPos >> 3) * 128 + (xPos >> 3)] & 0xff;
318 :
vram[tile * 64 + (yPos & 7) * 8 + (xPos & 7)] >> 8;
320 if (((
bool)(pixel & 0x80)) != priority)
return 0;
341 if (
windowLayer[layer].window1inversed) test1 = !test1;
342 if (
windowLayer[layer].window2inversed) test2 = !test2;
345 return test1 || test2;
347 return test1 && test2;
349 return test1 != test2;
351 return test1 == test2;
361 column = ((x - (x & 0xf)) - ((
bg_layer_[layer].
hScroll * 2) & 0xfff0)) >> 4;
367 int valid = layer == 0 ? 0x2000 : 0x4000;
369 uint16_t vOffset = 0;
371 if (hOffset & 0x8000) {
381 *lx = (((hOffset & 0x3f8) + (column * 8)) * 2) | (x & 0xf);
383 if (hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7);
387 *ly = (vOffset & 0x3ff) + (y -
bg_layer_[layer].vScroll);
396 uint16_t tilemapAdr =
398 (((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f));
399 if ((x & tileHighBit) &&
bg_layer_[2].tilemapWider) tilemapAdr += 0x400;
400 if ((y & tileHighBit) &&
bg_layer_[2].tilemapHigher)
402 return vram[tilemapAdr & 0x7fff];
408 int tileBitsX = wideTiles ? 4 : 3;
409 int tileHighBitX = wideTiles ? 0x200 : 0x100;
412 uint16_t tilemapAdr =
414 (((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f));
415 if ((x & tileHighBitX) &&
bg_layer_[layer].tilemapWider) tilemapAdr += 0x400;
416 if ((y & tileHighBitY) &&
bg_layer_[layer].tilemapHigher)
418 uint16_t tile =
vram[tilemapAdr & 0x7fff];
420 if (((
bool)(tile & 0x2000)) != priority)
return 0;
421 int paletteNum = (tile & 0x1c00) >> 10;
423 int row = (tile & 0x8000) ? 7 - (y & 0x7) : (y & 0x7);
424 int col = (tile & 0x4000) ? (x & 0x7) : 7 - (x & 0x7);
425 int tileNum = tile & 0x3ff;
428 if (((
bool)(x & 8)) ^ ((
bool)(tile & 0x4000))) tileNum += 1;
432 if (((
bool)(y & 8)) ^ ((
bool)(tile & 0x8000))) tileNum += 0x10;
435 int bitDepth = kBitDepthsPerMode[
mode][layer];
436 if (
mode == 0) paletteNum += 8 * layer;
440 ((tileNum & 0x3ff) * 4 * bitDepth) + row) &
442 int pixel = (plane1 >> col) & 1;
443 pixel |= ((plane1 >> (8 + col)) & 1) << 1;
448 ((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) &
450 pixel |= ((plane2 >> col) & 1) << 2;
451 pixel |= ((plane2 >> (8 + col)) & 1) << 3;
457 ((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) &
459 pixel |= ((plane3 >> col) & 1) << 4;
460 pixel |= ((plane3 >> (8 + col)) & 1) << 5;
462 ((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) &
464 pixel |= ((plane4 >> col) & 1) << 6;
465 pixel |= ((plane4 >> (8 + col)) & 1) << 7;
469 return pixel == 0 ? 0 : paletteSize * paletteNum + pixel;
475 int spritesFound = 0;
477 uint8_t foundSprites[32] = {};
479 for (
int i = 0; i < 128; i++) {
480 uint8_t y =
oam[index] >> 8;
482 uint8_t row = line - y;
485 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
487 if (row < spriteHeight) {
489 int x =
oam[index] & 0xff;
490 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
491 if (x > 255) x -= 512;
493 if (x > -spriteSize) {
496 if (spritesFound > 32) {
501 foundSprites[spritesFound - 1] = index;
507 for (
int i = spritesFound; i > 0; i--) {
508 index = foundSprites[i - 1];
509 uint8_t y =
oam[index] >> 8;
510 uint8_t row = line - y;
513 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
514 int x =
oam[index] & 0xff;
515 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
516 if (x > 255) x -= 512;
517 if (x > -spriteSize) {
521 int tile =
oam[index + 1] & 0xff;
522 int palette = (
oam[index + 1] & 0xe00) >> 9;
523 bool hFlipped =
oam[index + 1] & 0x4000;
524 if (
oam[index + 1] & 0x8000) row = spriteSize - 1 - row;
526 for (
int col = 0; col < spriteSize; col += 8) {
527 if (col + x > -8 && col + x < 256) {
530 if (tilesFound > 34) {
536 int usedCol = hFlipped ? spriteSize - 1 - col : col;
537 uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) |
538 (((tile & 0xf) + (usedCol / 8)) & 0xf);
542 vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff];
544 vram[(objAdr + usedTile * 16 + 8 + (row & 0x7)) & 0x7fff];
546 for (
int px = 0; px < 8; px++) {
547 int shift = hFlipped ? px : 7 - px;
548 int pixel = (plane1 >> shift) & 1;
549 pixel |= ((plane1 >> (8 + shift)) & 1) << 1;
550 pixel |= ((plane2 >> shift) & 1) << 2;
551 pixel |= ((plane2 >> (8 + shift)) & 1) << 3;
553 int screenCol = col + x + px;
554 if (pixel > 0 && screenCol >= 0 && screenCol < 256) {
569 int hScroll = ((int16_t)(
m7matrix[6] << 3)) >> 3;
570 int vScroll = ((int16_t)(
m7matrix[7] << 3)) >> 3;
571 int xCenter = ((int16_t)(
m7matrix[4] << 3)) >> 3;
572 int yCenter = ((int16_t)(
m7matrix[5] << 3)) >> 3;
574 int clippedH = hScroll - xCenter;
575 int clippedV = vScroll - yCenter;
576 clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023);
577 clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023);
581 uint8_t ry =
m7yFlip ? 255 - y : y;
583 ((
m7matrix[1] * clippedV) & ~63) + (xCenter << 8));
585 ((
m7matrix[3] * clippedV) & ~63) + (yCenter << 8));
846 if ((val & 3) == 0) {
848 }
else if ((val & 3) == 1) {
870 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0xff00) | val;
876 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8);
918 windowLayer[(adr - 0x23) * 2].window1inversed = val & 0x1;
919 windowLayer[(adr - 0x23) * 2].window1enabled = val & 0x2;
920 windowLayer[(adr - 0x23) * 2].window2inversed = val & 0x4;
921 windowLayer[(adr - 0x23) * 2].window2enabled = val & 0x8;
922 windowLayer[(adr - 0x23) * 2 + 1].window1inversed = val & 0x10;
923 windowLayer[(adr - 0x23) * 2 + 1].window1enabled = val & 0x20;
924 windowLayer[(adr - 0x23) * 2 + 1].window2inversed = val & 0x40;
925 windowLayer[(adr - 0x23) * 2 + 1].window2enabled = val & 0x80;
998 for (
int i = 0; i < 6; i++) {
1029 return (adr & 0xff00) | ((adr & 0xe0) >> 5) | ((adr & 0x1f) << 3);
1031 return (adr & 0xfe00) | ((adr & 0x1c0) >> 6) | ((adr & 0x3f) << 3);
1033 return (adr & 0xfc00) | ((adr & 0x380) >> 7) | ((adr & 0x7f) << 3);
1041 int y1 = y, y2 = y + 239;
1046 memcpy(pixels + (dest * 2048), &
pixelBuffer[y1 * 2048], 2048);
1047 memcpy(pixels + ((dest + 1) * 2048), &
pixelBuffer[y2 * 2048], 2048);
1050 memset(pixels, 0, 2048 * 2);
1052 memset(pixels + (2 * 2048), 0, 2048 * 14);
1053 memset(pixels + (464 * 2048), 0, 2048 * 16);