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++) {
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);
227 ((b2 << 3) | (b2 >> 2));
229 ((g2 << 3) | (g2 >> 2));
231 ((r2 << 3) | (r2 >> 2));
236 ((b << 3) | (b >> 2));
238 ((g << 3) | (g >> 2));
240 ((r << 3) | (r >> 2));
253 for (
int i = 0; i < kLayerCountPerMode[actMode]; i++) {
254 int curLayer = kLayersPerMode[actMode][i];
255 int curPriority = kPrioritysPerMode[actMode][i];
256 bool layerActive =
false;
306 if (
direct_color_ && layer < 4 && kBitDepthsPerMode[actMode][layer] == 8) {
307 *r = ((pixel & 0x7) << 2) | ((pixel & 0x100) >> 7);
308 *g = ((pixel & 0x38) >> 1) | ((pixel & 0x200) >> 8);
309 *b = ((pixel & 0xc0) >> 3) | ((pixel & 0x400) >> 8);
311 uint16_t color =
cgram[pixel & 0xff];
313 *g = (color >> 5) & 0x1f;
314 *b = (color >> 10) & 0x1f;
316 if (layer == 4 && pixel < 0xc0)
322 uint8_t rx =
m7xFlip ? 255 - x : x;
325 bool outsideMap = xPos < 0 || xPos >= 1024 || yPos < 0 || yPos >= 1024;
329 uint8_t tile = outsideMap ? 0 :
vram[(yPos >> 3) * 128 + (xPos >> 3)] & 0xff;
332 :
vram[tile * 64 + (yPos & 7) * 8 + (xPos & 7)] >> 8;
334 if (((
bool)(pixel & 0x80)) != priority)
return 0;
355 if (
windowLayer[layer].window1inversed) test1 = !test1;
356 if (
windowLayer[layer].window2inversed) test2 = !test2;
359 return test1 || test2;
361 return test1 && test2;
363 return test1 != test2;
365 return test1 == test2;
375 column = ((x - (x & 0xf)) - ((
bg_layer_[layer].
hScroll * 2) & 0xfff0)) >> 4;
381 int valid = layer == 0 ? 0x2000 : 0x4000;
383 uint16_t vOffset = 0;
385 if (hOffset & 0x8000) {
395 *lx = (((hOffset & 0x3f8) + (column * 8)) * 2) | (x & 0xf);
397 if (hOffset & valid) *lx = ((hOffset & 0x3f8) + (column * 8)) | (x & 0x7);
401 *ly = (vOffset & 0x3ff) + (y -
bg_layer_[layer].vScroll);
410 uint16_t tilemapAdr =
412 (((y >> tileBits) & 0x1f) << 5 | ((x >> tileBits) & 0x1f));
415 tilemapAdr +=
bg_layer_[2].tilemapWider ? 0x800 : 0x400;
416 return vram[tilemapAdr & 0x7fff];
422 int tileBitsX = wideTiles ? 4 : 3;
423 int tileHighBitX = wideTiles ? 0x200 : 0x100;
426 uint16_t tilemapAdr =
428 (((y >> tileBitsY) & 0x1f) << 5 | ((x >> tileBitsX) & 0x1f));
431 tilemapAdr +=
bg_layer_[layer].tilemapWider ? 0x800 : 0x400;
432 uint16_t tile =
vram[tilemapAdr & 0x7fff];
434 if (((
bool)(tile & 0x2000)) != priority)
return 0;
435 int paletteNum = (tile & 0x1c00) >> 10;
437 int row = (tile & 0x8000) ? 7 - (y & 0x7) : (y & 0x7);
438 int col = (tile & 0x4000) ? (x & 0x7) : 7 - (x & 0x7);
439 int tileNum = tile & 0x3ff;
442 if (((
bool)(x & 8)) ^ ((bool)(tile & 0x4000))) tileNum += 1;
446 if (((
bool)(y & 8)) ^ ((bool)(tile & 0x8000))) tileNum += 0x10;
449 int bitDepth = kBitDepthsPerMode[
mode][layer];
450 if (
mode == 0) paletteNum += 8 * layer;
454 ((tileNum & 0x3ff) * 4 * bitDepth) + row) &
456 int pixel = (plane1 >> col) & 1;
457 pixel |= ((plane1 >> (8 + col)) & 1) << 1;
462 ((tileNum & 0x3ff) * 4 * bitDepth) + 8 + row) &
464 pixel |= ((plane2 >> col) & 1) << 2;
465 pixel |= ((plane2 >> (8 + col)) & 1) << 3;
471 ((tileNum & 0x3ff) * 4 * bitDepth) + 16 + row) &
473 pixel |= ((plane3 >> col) & 1) << 4;
474 pixel |= ((plane3 >> (8 + col)) & 1) << 5;
476 ((tileNum & 0x3ff) * 4 * bitDepth) + 24 + row) &
478 pixel |= ((plane4 >> col) & 1) << 6;
479 pixel |= ((plane4 >> (8 + col)) & 1) << 7;
483 return pixel == 0 ? 0 : paletteSize * paletteNum + pixel;
489 int spritesFound = 0;
491 uint8_t foundSprites[32] = {};
493 for (
int i = 0; i < 128; i++) {
494 uint8_t y =
oam[index] >> 8;
496 uint8_t row = line - y;
499 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
501 if (row < spriteHeight) {
503 int x =
oam[index] & 0xff;
504 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
505 if (x > 255) x -= 512;
507 if (x > -spriteSize) {
510 if (spritesFound > 32) {
515 foundSprites[spritesFound - 1] = index;
521 for (
int i = spritesFound; i > 0; i--) {
522 index = foundSprites[i - 1];
523 uint8_t y =
oam[index] >> 8;
524 uint8_t row = line - y;
527 [(
high_oam_[index >> 3] >> ((index & 7) + 1)) & 1];
528 int x =
oam[index] & 0xff;
529 x |= ((
high_oam_[index >> 3] >> (index & 7)) & 1) << 8;
530 if (x > 255) x -= 512;
531 if (x > -spriteSize) {
535 int tile =
oam[index + 1] & 0xff;
536 int palette = (
oam[index + 1] & 0xe00) >> 9;
537 bool hFlipped =
oam[index + 1] & 0x4000;
538 if (
oam[index + 1] & 0x8000) row = spriteSize - 1 - row;
540 for (
int col = 0; col < spriteSize; col += 8) {
541 if (col + x > -8 && col + x < 256) {
544 if (tilesFound > 34) {
550 int usedCol = hFlipped ? spriteSize - 1 - col : col;
551 uint8_t usedTile = (((tile >> 4) + (row / 8)) << 4) |
552 (((tile & 0xf) + (usedCol / 8)) & 0xf);
556 vram[(objAdr + usedTile * 16 + (row & 0x7)) & 0x7fff];
558 vram[(objAdr + usedTile * 16 + 8 + (row & 0x7)) & 0x7fff];
560 for (
int px = 0; px < 8; px++) {
561 int shift = hFlipped ? px : 7 - px;
562 int pixel = (plane1 >> shift) & 1;
563 pixel |= ((plane1 >> (8 + shift)) & 1) << 1;
564 pixel |= ((plane2 >> shift) & 1) << 2;
565 pixel |= ((plane2 >> (8 + shift)) & 1) << 3;
567 int screenCol = col + x + px;
568 if (pixel > 0 && screenCol >= 0 && screenCol < 256) {
583 int hScroll = ((int16_t)(
m7matrix[6] << 3)) >> 3;
584 int vScroll = ((int16_t)(
m7matrix[7] << 3)) >> 3;
585 int xCenter = ((int16_t)(
m7matrix[4] << 3)) >> 3;
586 int yCenter = ((int16_t)(
m7matrix[5] << 3)) >> 3;
588 int clippedH = hScroll - xCenter;
589 int clippedV = vScroll - yCenter;
590 clippedH = (clippedH & 0x2000) ? (clippedH | ~1023) : (clippedH & 1023);
591 clippedV = (clippedV & 0x2000) ? (clippedV | ~1023) : (clippedV & 1023);
595 uint8_t ry =
m7yFlip ? 255 - y : y;
597 ((
m7matrix[1] * clippedV) & ~63) + (xCenter << 8));
599 ((
m7matrix[3] * clippedV) & ~63) + (yCenter << 8));
860 if ((val & 3) == 0) {
862 }
else if ((val & 3) == 1) {
884 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0xff00) | val;
890 vram[vramAdr & 0x7fff] = (
vram[vramAdr & 0x7fff] & 0x00ff) | (val << 8);
932 windowLayer[(adr - 0x23) * 2].window1inversed = val & 0x1;
933 windowLayer[(adr - 0x23) * 2].window1enabled = val & 0x2;
934 windowLayer[(adr - 0x23) * 2].window2inversed = val & 0x4;
935 windowLayer[(adr - 0x23) * 2].window2enabled = val & 0x8;
936 windowLayer[(adr - 0x23) * 2 + 1].window1inversed = val & 0x10;
937 windowLayer[(adr - 0x23) * 2 + 1].window1enabled = val & 0x20;
938 windowLayer[(adr - 0x23) * 2 + 1].window2inversed = val & 0x40;
939 windowLayer[(adr - 0x23) * 2 + 1].window2enabled = val & 0x80;
1012 for (
int i = 0; i < 6; i++) {
1043 return (adr & 0xff00) | ((adr & 0xe0) >> 5) | ((adr & 0x1f) << 3);
1045 return (adr & 0xfe00) | ((adr & 0x1c0) >> 6) | ((adr & 0x3f) << 3);
1047 return (adr & 0xfc00) | ((adr & 0x380) >> 7) | ((adr & 0x7f) << 3);
1055 int y1 = y, y2 = y + 239;
1060 memcpy(pixels + (dest * 2048), &
pixelBuffer[y1 * 2048], 2048);
1061 memcpy(pixels + ((dest + 1) * 2048), &
pixelBuffer[y2 * 2048], 2048);
1064 memset(pixels, 0, 2048 * 2);
1066 memset(pixels + (2 * 2048), 0, 2048 * 14);
1067 memset(pixels + (464 * 2048), 0, 2048 * 16);
virtual auto pal_timing() const -> bool=0
virtual auto v_pos() const -> uint16_t=0
virtual uint8_t open_bus() const =0
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_
Main namespace for the application.