16static const int kLayersPerMode[10][12] = {
17 {4, 0, 1, 4, 0, 1, 4, 2, 3, 4, 2, 3}, {4, 0, 1, 4, 0, 1, 4, 2, 4, 2, 5, 5},
18 {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
19 {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5}, {4, 0, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5},
20 {4, 0, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5}, {4, 4, 4, 0, 4, 5, 5, 5, 5, 5, 5, 5},
21 {2, 4, 0, 1, 4, 0, 1, 4, 4, 2, 5, 5}, {4, 4, 1, 4, 0, 4, 1, 5, 5, 5, 5, 5}};
23static const int kPrioritysPerMode[10][12] = {
24 {3, 1, 1, 2, 0, 0, 1, 1, 1, 0, 0, 0}, {3, 1, 1, 2, 0, 0, 1, 1, 0, 0, 5, 5},
25 {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
26 {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5}, {3, 1, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5},
27 {3, 1, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5}, {3, 2, 1, 0, 0, 5, 5, 5, 5, 5, 5, 5},
28 {1, 3, 1, 1, 2, 0, 0, 1, 0, 0, 5, 5}, {3, 2, 1, 1, 0, 0, 0, 5, 5, 5, 5, 5}};
30static const int kLayerCountPerMode[10] = {12, 10, 8, 8, 8, 8, 6, 5, 10, 7};
32static const int kBitDepthsPerMode[10][4] = {
33 {2, 2, 2, 2}, {4, 4, 2, 5}, {4, 4, 5, 5}, {8, 4, 5, 5}, {8, 2, 5, 5},
34 {4, 2, 5, 5}, {4, 5, 5, 5}, {8, 5, 5, 5}, {4, 4, 2, 5}, {8, 7, 5, 5}};
36static const int kSpriteSizes[8][2] = {{8, 16}, {8, 32}, {8, 64}, {16, 32},
37 {16, 64}, {32, 64}, {16, 32}, {16, 32}};
50 memset(
oam, 0,
sizeof(
oam));
67 for (
int i = 0; i < 4; i++) {
81 for (
int i = 0; i < 5; i++) {
82 layer_[i].mainScreenEnabled =
false;
83 layer_[i].subScreenEnabled =
false;
84 layer_[i].mainScreenWindowed =
false;
85 layer_[i].subScreenWindowed =
false;
96 for (
int i = 0; i < 6; i++) {
152 for (
int x = 0; x < 256; x++) {
162 int mainLayer =
GetPixel(x, y,
false, &r, &g, &b);
177 secondLayer =
GetPixel(x, y,
true, &r2, &g2, &b2);
233 for (
int i = 0; i < kLayerCountPerMode[actMode]; i++) {
234 int curLayer = kLayersPerMode[actMode][i];
235 int curPriority = kPrioritysPerMode[actMode][i];
236 bool layerActive =
false;
238 layerActive =
layer_[curLayer].mainScreenEnabled &&
239 (!
layer_[curLayer].mainScreenWindowed ||
243 layer_[curLayer].subScreenEnabled &&
261 lx += (subscreen ||
bg_layer_[curLayer].mosaicEnabled) ? 0 : 1;
286 if (
direct_color_ && layer < 4 && kBitDepthsPerMode[actMode][layer] == 8) {
287 *r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7);
288 *g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8);
289 *b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8);
291 uint16_t color =
cgram[pixel & 0xff];
293 *g = (color >> 5) & 0x1f;
294 *b = (color >> 10) & 0x1f;
296 if (layer == 4 && pixel < 0xc0)
302 uint8_t rx =
m7xFlip ? 255 - x : x;
305 bool outsideMap = xPos < 0 || xPos >= 1024 || yPos < 0 || yPos >= 1024;
309 uint8_t tile = outsideMap ? 0 :
vram[(yPos >> 3) * 128 + (xPos >> 3)] & 0xff;
312 :
vram[tile * 64 + (yPos & 7) * 8 + (xPos & 7)] >> 8;
314 if (((
bool)(pixel & 0x80)) != priority)
return 0;
335 if (
windowLayer[layer].window1inversed) test1 = !test1;
336 if (
windowLayer[layer].window2inversed) test2 = !test2;
339 return test1 || test2;
341 return test1 && test2;
343 return test1 != test2;
345 return test1 == test2;
355 column = ((x - (x & 0xf)) - ((
bg_layer_[layer].hScroll * 2) & 0xfff0)) >> 4;
357 column = ((x - (x & 0x7)) - (
bg_layer_[layer].hScroll & 0xfff8)) >> 3;
361 int valid = layer == 0 ? 0x2000 : 0x4000;
363 uint16_t vOffset = 0;
365 if (hOffset & 0x8000) {
375 *lx = (((hOffset & 0x3f8) + (column * 8)) * 2) | (x & 0xf);
377 if (hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7);
381 *ly = (vOffset & 0x3ff) + (y -
bg_layer_[layer].vScroll);
388 int tileBits =
bg_layer_[2].bigTiles ? 4 : 3;
389 int tileHighBit =
bg_layer_[2].bigTiles ? 0x200 : 0x100;
390 uint16_t tilemapAdr =
392 (((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f));
393 if ((x & tileHighBit) &&
bg_layer_[2].tilemapWider) tilemapAdr += 0x400;
394 if ((y & tileHighBit) &&
bg_layer_[2].tilemapHigher)
395 tilemapAdr +=
bg_layer_[2].tilemapWider ? 0x800 : 0x400;
396 return vram[tilemapAdr & 0x7fff];
402 int tileBitsX = wideTiles ? 4 : 3;
403 int tileHighBitX = wideTiles ? 0x200 : 0x100;
404 int tileBitsY =
bg_layer_[layer].bigTiles ? 4 : 3;
405 int tileHighBitY =
bg_layer_[layer].bigTiles ? 0x200 : 0x100;
406 uint16_t tilemapAdr =
408 (((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f));
409 if ((x & tileHighBitX) &&
bg_layer_[layer].tilemapWider) tilemapAdr += 0x400;
410 if ((y & tileHighBitY) &&
bg_layer_[layer].tilemapHigher)
411 tilemapAdr +=
bg_layer_[layer].tilemapWider ? 0x800 : 0x400;
412 uint16_t tile =
vram[tilemapAdr & 0x7fff];
414 if (((
bool)(tile & 0x2000)) != priority)
return 0;
415 int paletteNum = (tile & 0x1c00) >> 10;
417 int row = (tile & 0x8000) ? 7 - (y & 0x7) : (y & 0x7);
418 int col = (tile & 0x4000) ? (x & 0x7) : 7 - (x & 0x7);
419 int tileNum = tile & 0x3ff;
422 if (((
bool)(x & 8)) ^ ((
bool)(tile & 0x4000))) tileNum += 1;
426 if (((
bool)(y & 8)) ^ ((
bool)(tile & 0x8000))) tileNum += 0x10;
429 int bitDepth = kBitDepthsPerMode[
mode][layer];
430 if (
mode == 0) paletteNum += 8 * layer;
434 ((tileNum & 0x3ff) * 4 * bitDepth) + row) &
436 int pixel = (plane1 >> col) & 1;
437 pixel |= ((plane1 >> (8 + col)) & 1) << 1;
442 ((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) &
444 pixel |= ((plane2 >> col) & 1) << 2;
445 pixel |= ((plane2 >> (8 + col)) & 1) << 3;
451 ((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) &
453 pixel |= ((plane3 >> col) & 1) << 4;
454 pixel |= ((plane3 >> (8 + col)) & 1) << 5;
456 ((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) &
458 pixel |= ((plane4 >> col) & 1) << 6;
459 pixel |= ((plane4 >> (8 + col)) & 1) << 7;
463 return pixel == 0 ? 0 : paletteSize * paletteNum + pixel;
469 int spritesFound = 0;
471 uint8_t foundSprites[32] = {};
473 for (
int i = 0; i < 128; i++) {
474 uint8_t y =
oam[index] >> 8;
476 uint8_t row = line - y;
479 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
481 if (row < spriteHeight) {
483 int x =
oam[index] & 0xff;
484 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
485 if (x > 255) x -= 512;
487 if (x > -spriteSize) {
490 if (spritesFound > 32) {
495 foundSprites[spritesFound - 1] = index;
501 for (
int i = spritesFound; i > 0; i--) {
502 index = foundSprites[i - 1];
503 uint8_t y =
oam[index] >> 8;
504 uint8_t row = line - y;
507 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
508 int x =
oam[index] & 0xff;
509 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
510 if (x > 255) x -= 512;
511 if (x > -spriteSize) {
515 int tile =
oam[index + 1] & 0xff;
516 int palette = (
oam[index + 1] & 0xe00) >> 9;
517 bool hFlipped =
oam[index + 1] & 0x4000;
518 if (
oam[index + 1] & 0x8000) row = spriteSize - 1 - row;
520 for (
int col = 0; col < spriteSize; col += 8) {
521 if (col + x > -8 && col + x < 256) {
524 if (tilesFound > 34) {
530 int usedCol = hFlipped ? spriteSize - 1 - col : col;
531 uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) |
532 (((tile & 0xf) + (usedCol / 8)) & 0xf);
536 vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff];
538 vram[(objAdr + usedTile * 16 + 8 + (row & 0x7)) & 0x7fff];
540 for (
int px = 0; px < 8; px++) {
541 int shift = hFlipped ? px : 7 - px;
542 int pixel = (plane1 >> shift) & 1;
543 pixel |= ((plane1 >> (8 + shift)) & 1) << 1;
544 pixel |= ((plane2 >> shift) & 1) << 2;
545 pixel |= ((plane2 >> (8 + shift)) & 1) << 3;
547 int screenCol = col + x + px;
548 if (pixel > 0 && screenCol >= 0 && screenCol < 256) {
563 int hScroll = ((int16_t)(
m7matrix[6] << 3)) >> 3;
564 int vScroll = ((int16_t)(
m7matrix[7] << 3)) >> 3;
565 int xCenter = ((int16_t)(
m7matrix[4] << 3)) >> 3;
566 int yCenter = ((int16_t)(
m7matrix[5] << 3)) >> 3;
568 int clippedH = hScroll - xCenter;
569 int clippedV = vScroll - yCenter;
570 clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023);
571 clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023);
575 uint8_t ry =
m7yFlip ? 255 - y : y;
577 ((
m7matrix[1] * clippedV) & ~63) + (xCenter << 8));
579 ((
m7matrix[3] * clippedV) & ~63) + (yCenter << 8));
709 val |=
memory_.pal_timing() << 4;
798 bg_layer_[adr - 7].tilemapWider = val & 0x1;
799 bg_layer_[adr - 7].tilemapHigher = val & 0x2;
800 bg_layer_[adr - 7].tilemapAdr = (val & 0xfc) << 8;
804 bg_layer_[0].tileAdr = (val & 0xf) << 12;
805 bg_layer_[1].tileAdr = (val & 0xf0) << 8;
809 bg_layer_[2].tileAdr = (val & 0xf) << 12;
810 bg_layer_[3].tileAdr = (val & 0xf0) << 8;
840 if ((val & 3) == 0) {
842 }
else if ((val & 3) == 1) {
864 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0xff00) | val;
870 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8);
912 windowLayer[(adr - 0x23) * 2].window1inversed = val & 0x1;
913 windowLayer[(adr - 0x23) * 2].window1enabled = val & 0x2;
914 windowLayer[(adr - 0x23) * 2].window2inversed = val & 0x4;
915 windowLayer[(adr - 0x23) * 2].window2enabled = val & 0x8;
916 windowLayer[(adr - 0x23) * 2 + 1].window1inversed = val & 0x10;
917 windowLayer[(adr - 0x23) * 2 + 1].window1enabled = val & 0x20;
918 windowLayer[(adr - 0x23) * 2 + 1].window2inversed = val & 0x40;
919 windowLayer[(adr - 0x23) * 2 + 1].window2enabled = val & 0x80;
951 layer_[0].mainScreenEnabled = val & 0x1;
952 layer_[1].mainScreenEnabled = val & 0x2;
953 layer_[2].mainScreenEnabled = val & 0x4;
954 layer_[3].mainScreenEnabled = val & 0x8;
955 layer_[4].mainScreenEnabled = val & 0x10;
959 layer_[0].subScreenEnabled = val & 0x1;
960 layer_[1].subScreenEnabled = val & 0x2;
961 layer_[2].subScreenEnabled = val & 0x4;
962 layer_[3].subScreenEnabled = val & 0x8;
963 layer_[4].subScreenEnabled = val & 0x10;
967 layer_[0].mainScreenWindowed = val & 0x1;
968 layer_[1].mainScreenWindowed = val & 0x2;
969 layer_[2].mainScreenWindowed = val & 0x4;
970 layer_[3].mainScreenWindowed = val & 0x8;
971 layer_[4].mainScreenWindowed = val & 0x10;
975 layer_[0].subScreenWindowed = val & 0x1;
976 layer_[1].subScreenWindowed = val & 0x2;
977 layer_[2].subScreenWindowed = val & 0x4;
978 layer_[3].subScreenWindowed = val & 0x8;
979 layer_[4].subScreenWindowed = val & 0x10;
992 for (
int i = 0; i < 6; i++) {
1023 return (adr & 0xff00) | ((adr & 0xe0) >> 5) | ((adr & 0x1f) << 3);
1025 return (adr & 0xfe00) | ((adr & 0x1c0) >> 6) | ((adr & 0x3f) << 3);
1027 return (adr & 0xfc00) | ((adr & 0x380) >> 7) | ((adr & 0x7f) << 3);
1035 int y1 = y, y2 = y + 239;
1040 memcpy(pixels + (dest * 2048), &
pixelBuffer[y1 * 2048], 2048);
1041 memcpy(pixels + ((dest + 1) * 2048), &
pixelBuffer[y2 * 2048], 2048);
1044 memset(pixels, 0, 2048 * 2);
1046 memset(pixels + (2 * 2048), 0, 2048 * 14);
1047 memset(pixels + (464 * 2048), 0, 2048 * 16);
void HandleOPT(int layer, int *lx, int *ly)
void HandlePixel(int x, int y)
void EvaluateSprites(int line)
uint8_t pixelBuffer[512 *4 *239 *2]
int GetPixel(int x, int y, bool sub, int *r, int *g, int *b)
uint8_t prevent_math_mode_
bool GetWindowState(int layer, int x)
void CalculateMode7Starts(int y)
bool vram_increment_on_high_
void Write(uint8_t adr, uint8_t val)
std::array< uint8_t, 256 > obj_pixel_buffer_
void PutPixels(uint8_t *pixel_data)
std::array< uint8_t, 256 > obj_priority_buffer_
uint8_t Read(uint8_t adr, bool latch)
uint8_t mosaic_startline_
bool oam_in_high_written_
uint8_t pixelOutputFormat
uint16_t GetOffsetValue(int col, int row)
bool math_enabled_array_[6]
int GetPixelForBgLayer(int x, int y, int layer, bool priority)
int GetPixelForMode7(int x, int layer, bool priority)
WindowLayer windowLayer[6]
uint16_t vram_read_buffer_
SNES Emulation and debugging tools.
Main namespace for the application.