comparison vdp.c @ 1696:956c1cce05e2 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Thu, 24 Jan 2019 19:15:59 -0800
parents 3128d4e0bc68
children 8f2e78db0872
comparison
equal deleted inserted replaced
1648:b7ecd0d6a77b 1696:956c1cce05e2
3 This file is part of BlastEm. 3 This file is part of BlastEm.
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text. 4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
5 */ 5 */
6 #include "vdp.h" 6 #include "vdp.h"
7 #include "blastem.h" 7 #include "blastem.h"
8 #include "genesis.h"
9 #include <stdlib.h> 8 #include <stdlib.h>
10 #include <string.h> 9 #include <string.h>
11 #include "render.h" 10 #include "render.h"
12 #include "util.h" 11 #include "util.h"
13 12
769 #define BG_START_SLOT 6 768 #define BG_START_SLOT 6
770 769
771 static void update_color_map(vdp_context *context, uint16_t index, uint16_t value) 770 static void update_color_map(vdp_context *context, uint16_t index, uint16_t value)
772 { 771 {
773 context->colors[index] = color_map[value & CRAM_BITS]; 772 context->colors[index] = color_map[value & CRAM_BITS];
774 context->colors[index + CRAM_SIZE] = color_map[(value & CRAM_BITS) | FBUF_SHADOW]; 773 context->colors[index + SHADOW_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_SHADOW];
775 context->colors[index + CRAM_SIZE*2] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT]; 774 context->colors[index + HIGHLIGHT_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_HILIGHT];
776 context->colors[index + CRAM_SIZE*3] = color_map[(value & CRAM_BITS) | FBUF_MODE4]; 775 context->colors[index + MODE4_OFFSET] = color_map[(value & CRAM_BITS) | FBUF_MODE4];
777 } 776 }
778 777
779 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value) 778 void write_cram_internal(vdp_context * context, uint16_t addr, uint16_t value)
780 { 779 {
781 context->cram[addr] = value; 780 context->cram[addr] = value;
797 context->vcounter < context->inactive_start + context->border_bot 796 context->vcounter < context->inactive_start + context->border_bot
798 || context->vcounter > 0x200 - context->border_top 797 || context->vcounter > 0x200 - context->border_top
799 )) { 798 )) {
800 uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2; 799 uint8_t bg_end_slot = BG_START_SLOT + (context->regs[REG_MODE_4] & BIT_H40) ? LINEBUF_SIZE/2 : (256+HORIZ_BORDER)/2;
801 if (context->hslot < bg_end_slot) { 800 if (context->hslot < bg_end_slot) {
802 uint32_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->colors[addr] : context->colors[addr + CRAM_SIZE*3]; 801 uint32_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) ? context->colors[addr] : context->colors[addr + MODE4_OFFSET];
803 context->output[(context->hslot - BG_START_SLOT)*2 + 1] = color; 802 context->output[(context->hslot - BG_START_SLOT)*2 + 1] = color;
804 } 803 }
805 } 804 }
806 } 805 }
807 806
1207 if (col & MAP_BIT_V_FLIP) { 1206 if (col & MAP_BIT_V_FLIP) {
1208 address += vflip_base - 4 * context->v_offset; 1207 address += vflip_base - 4 * context->v_offset;
1209 } else { 1208 } else {
1210 address += 4 * context->v_offset; 1209 address += 4 * context->v_offset;
1211 } 1210 }
1212 uint16_t pal_priority = (col >> 9) & 0x70; 1211 uint8_t pal_priority = (col >> 9) & 0x70;
1213 int32_t dir; 1212 uint32_t bits = *((uint32_t *)(&context->vdpmem[address]));
1214 if (col & MAP_BIT_H_FLIP) { 1213 if (col & MAP_BIT_H_FLIP) {
1215 offset += 7; 1214 uint32_t shift = 28;
1216 offset &= SCROLL_BUFFER_MASK; 1215 for (int i = 0; i < 4; i++)
1217 dir = -1; 1216 {
1218 } else { 1217 uint8_t right = pal_priority | ((bits >> shift) & 0xF);
1219 dir = 1; 1218 shift -= 4;
1220 } 1219 tmp_buf[offset++] = pal_priority | ((bits >> shift) & 0xF);
1221 for (uint32_t i=0; i < 4; i++, address++) 1220 shift -= 4;
1222 { 1221 offset &= SCROLL_BUFFER_MASK;
1223 tmp_buf[offset] = pal_priority | (context->vdpmem[address] >> 4); 1222 tmp_buf[offset++] = right;
1224 offset += dir; 1223 offset &= SCROLL_BUFFER_MASK;
1225 offset &= SCROLL_BUFFER_MASK; 1224 }
1226 tmp_buf[offset] = pal_priority | (context->vdpmem[address] & 0xF); 1225 } else {
1227 offset += dir; 1226 for (int i = 0; i < 4; i++)
1228 offset &= SCROLL_BUFFER_MASK; 1227 {
1228 uint8_t right = pal_priority | (bits & 0xF);
1229 bits >>= 4;
1230 tmp_buf[offset++] = pal_priority | (bits & 0xF);
1231 offset &= SCROLL_BUFFER_MASK;
1232 bits >>= 4;
1233 tmp_buf[offset++] = right;
1234 offset &= SCROLL_BUFFER_MASK;
1235 }
1229 } 1236 }
1230 } 1237 }
1231 1238
1232 static void render_map_1(vdp_context * context) 1239 static void render_map_1(vdp_context * context)
1233 { 1240 {
1260 } 1267 }
1261 1268
1262 uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4]; 1269 uint32_t address = mode4_address_map[((context->col_1 & 0x1FF) * 32) + vscroll * 4];
1263 context->fetch_tmp[0] = context->vdpmem[address]; 1270 context->fetch_tmp[0] = context->vdpmem[address];
1264 context->fetch_tmp[1] = context->vdpmem[address+1]; 1271 context->fetch_tmp[1] = context->vdpmem[address+1];
1272 }
1273
1274 static uint8_t composite_normal(vdp_context *context, uint8_t *debug_dst, uint8_t sprite, uint8_t plane_a, uint8_t plane_b, uint8_t bg_index)
1275 {
1276 uint8_t pixel = bg_index;
1277 uint8_t src = DBG_SRC_BG;
1278 if (plane_b & 0xF) {
1279 pixel = plane_b;
1280 src = DBG_SRC_B;
1281 }
1282 if (plane_a & 0xF && (plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1283 pixel = plane_a;
1284 src = DBG_SRC_A;
1285 }
1286 if (sprite & 0xF && (sprite & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1287 pixel = sprite;
1288 src = DBG_SRC_S;
1289 }
1290 *debug_dst = src;
1291 return pixel;
1292 }
1293 typedef struct {
1294 uint8_t index, intensity;
1295 } sh_pixel;
1296
1297 static sh_pixel composite_highlight(vdp_context *context, uint8_t *debug_dst, uint8_t sprite, uint8_t plane_a, uint8_t plane_b, uint8_t bg_index)
1298 {
1299 uint8_t pixel = bg_index;
1300 uint8_t src = DBG_SRC_BG;
1301 uint8_t intensity = 0;
1302 if (plane_b & 0xF) {
1303 pixel = plane_b;
1304 src = DBG_SRC_B;
1305 }
1306 intensity = plane_b & BUF_BIT_PRIORITY;
1307 if (plane_a & 0xF && (plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1308 pixel = plane_a;
1309 src = DBG_SRC_A;
1310 }
1311 intensity |= plane_a & BUF_BIT_PRIORITY;
1312 if (sprite & 0xF && (sprite & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1313 if ((sprite & 0x3F) == 0x3E) {
1314 intensity += BUF_BIT_PRIORITY;
1315 } else if ((sprite & 0x3F) == 0x3F) {
1316 intensity = 0;
1317 } else {
1318 pixel = sprite;
1319 src = DBG_SRC_S;
1320 if ((pixel & 0xF) == 0xE) {
1321 intensity = BUF_BIT_PRIORITY;
1322 } else {
1323 intensity |= pixel & BUF_BIT_PRIORITY;
1324 }
1325 }
1326 }
1327 *debug_dst = src;
1328 return (sh_pixel){.index = pixel, .intensity = intensity};
1329 }
1330
1331 static void render_normal(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
1332 {
1333 int start = 0;
1334 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1335 uint32_t bgcolor = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1336 for (int i = 0; i < 8; ++i)
1337 {
1338 *(dst++) = bgcolor;
1339 *(debug_dst++) = DBG_SRC_BG;
1340 }
1341 start = 8;
1342 }
1343 uint8_t *sprite_buf = context->linebuf + col * 8 + start;
1344 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1345 {
1346 uint8_t sprite, plane_a, plane_b;
1347 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1348 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1349 sprite = *sprite_buf;
1350 uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]);
1351 debug_dst++;
1352 *(dst++) = context->colors[pixel & 0x3F];
1353 }
1354 }
1355
1356 static void render_highlight(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
1357 {
1358 int start = 0;
1359 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1360 uint32_t bgcolor = context->colors[SHADOW_OFFSET + (context->regs[REG_BG_COLOR] & 0x3F)];
1361 for (int i = 0; i < 8; ++i)
1362 {
1363 *(dst++) = bgcolor;
1364 *(debug_dst++) = DBG_SRC_BG | DBG_SHADOW;
1365 }
1366 start = 8;
1367 }
1368 uint8_t *sprite_buf = context->linebuf + col * 8 + start;
1369 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1370 {
1371 uint8_t sprite, plane_a, plane_b;
1372 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1373 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1374 sprite = *sprite_buf;
1375 sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]);
1376 uint32_t *colors;
1377 if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1378 colors = context->colors + HIGHLIGHT_OFFSET;
1379 } else if (pixel.intensity) {
1380 colors = context->colors;
1381 } else {
1382 colors = context->colors + SHADOW_OFFSET;
1383 }
1384 debug_dst++;
1385 *(dst++) = colors[pixel.index & 0x3F];
1386 }
1387 }
1388
1389 static void render_testreg(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1390 {
1391 if (output_disabled) {
1392 switch (test_layer)
1393 {
1394 case 0:
1395 for (int i = 0; i < 16; i++)
1396 {
1397 *(dst++) = 0x3F; //TODO: confirm this on hardware
1398 *(debug_dst++) = DBG_SRC_BG;
1399 }
1400 break;
1401 case 1: {
1402 uint8_t *sprite_buf = context->linebuf + col * 8;
1403 for (int i = 0; i < 16; i++)
1404 {
1405 *(dst++) = context->colors[*(sprite_buf++) & 0x3F];
1406 *(debug_dst++) = DBG_SRC_S;
1407 }
1408 break;
1409 }
1410 case 2:
1411 for (int i = 0; i < 16; i++)
1412 {
1413 *(dst++) = context->colors[context->tmp_buf_a[(plane_a_off++) & SCROLL_BUFFER_MASK] & 0x3F];
1414 *(debug_dst++) = DBG_SRC_A;
1415 }
1416 break;
1417 case 3:
1418 for (int i = 0; i < 16; i++)
1419 {
1420 *(dst++) = context->colors[context->tmp_buf_b[(plane_b_off++) & SCROLL_BUFFER_MASK] & 0x3F];
1421 *(debug_dst++) = DBG_SRC_B;
1422 }
1423 break;
1424 }
1425 } else {
1426 int start = 0;
1427 uint8_t *sprite_buf = context->linebuf + col * 8;
1428 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1429 //TODO: Confirm how test register interacts with column 0 blanking
1430 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1431 uint8_t src = DBG_SRC_BG;
1432 for (int i = 0; i < 8; ++i)
1433 {
1434 switch (test_layer)
1435 {
1436 case 1:
1437 pixel &= sprite_buf[i];
1438 if (pixel) {
1439 src = DBG_SRC_S;
1440 }
1441 break;
1442 case 2:
1443 pixel &= context->tmp_buf_a[(plane_a_off + i) & SCROLL_BUFFER_MASK];
1444 if (pixel) {
1445 src = DBG_SRC_A;
1446 }
1447 break;
1448 case 3:
1449 pixel &= context->tmp_buf_b[(plane_b_off + i) & SCROLL_BUFFER_MASK];
1450 if (pixel) {
1451 src = DBG_SRC_B;
1452 }
1453 break;
1454 }
1455
1456 *(dst++) = context->colors[pixel & 0x3F];
1457 *(debug_dst++) = src;
1458 }
1459 plane_a_off += 8;
1460 plane_b_off += 8;
1461 sprite_buf += 8;
1462 start = 8;
1463 }
1464 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1465 {
1466 uint8_t sprite, plane_a, plane_b;
1467 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1468 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1469 sprite = *sprite_buf;
1470 uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, 0x3F);
1471 switch (test_layer)
1472 {
1473 case 1:
1474 pixel &= sprite;
1475 if (pixel) {
1476 *debug_dst = DBG_SRC_S;
1477 }
1478 break;
1479 case 2:
1480 pixel &= plane_a;
1481 if (pixel) {
1482 *debug_dst = DBG_SRC_A;
1483 }
1484 break;
1485 case 3:
1486 pixel &= plane_b;
1487 if (pixel) {
1488 *debug_dst = DBG_SRC_B;
1489 }
1490 break;
1491 }
1492 debug_dst++;
1493 *(dst++) = context->colors[pixel & 0x3F];
1494 }
1495 }
1496 }
1497
1498 static void render_testreg_highlight(vdp_context *context, int32_t col, uint32_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1499 {
1500 int start = 0;
1501 uint8_t *sprite_buf = context->linebuf + col * 8;
1502 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1503 //TODO: Confirm how test register interacts with column 0 blanking
1504 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1505 uint8_t src = DBG_SRC_BG | DBG_SHADOW;
1506 for (int i = 0; i < 8; ++i)
1507 {
1508 switch (test_layer)
1509 {
1510 case 1:
1511 pixel &= sprite_buf[i];
1512 if (pixel) {
1513 src = DBG_SRC_S | DBG_SHADOW;
1514 }
1515 break;
1516 case 2:
1517 pixel &= context->tmp_buf_a[(plane_a_off + i) & SCROLL_BUFFER_MASK];
1518 if (pixel) {
1519 src = DBG_SRC_A | DBG_SHADOW;
1520 }
1521 break;
1522 case 3:
1523 pixel &= context->tmp_buf_b[(plane_b_off + i) & SCROLL_BUFFER_MASK];
1524 if (pixel) {
1525 src = DBG_SRC_B | DBG_SHADOW;
1526 }
1527 break;
1528 }
1529
1530 *(dst++) = context->colors[SHADOW_OFFSET + (pixel & 0x3F)];
1531 *(debug_dst++) = src;
1532 }
1533 plane_a_off += 8;
1534 plane_b_off += 8;
1535 sprite_buf += 8;
1536 start = 8;
1537 }
1538 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1539 {
1540 uint8_t sprite, plane_a, plane_b;
1541 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK];
1542 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1543 sprite = *sprite_buf;
1544 sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, 0x3F);
1545 uint32_t *colors;
1546 if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1547 colors = context->colors + HIGHLIGHT_OFFSET;
1548 } else if (pixel.intensity) {
1549 colors = context->colors;
1550 } else {
1551 colors = context->colors + SHADOW_OFFSET;
1552 }
1553 if (output_disabled) {
1554 pixel.index = 0x3F;
1555 }
1556 switch (test_layer)
1557 {
1558 case 1:
1559 pixel.index &= sprite;
1560 if (pixel.index) {
1561 *debug_dst = DBG_SRC_S;
1562 }
1563 break;
1564 case 2:
1565 pixel.index &= plane_a;
1566 if (pixel.index) {
1567 *debug_dst = DBG_SRC_A;
1568 }
1569 break;
1570 case 3:
1571 pixel.index &= plane_b;
1572 if (pixel.index) {
1573 *debug_dst = DBG_SRC_B;
1574 }
1575 break;
1576 }
1577 debug_dst++;
1578 *(dst++) = colors[pixel.index & 0x3F];
1579 }
1265 } 1580 }
1266 1581
1267 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) 1582 static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
1268 { 1583 {
1269 uint32_t *dst; 1584 uint32_t *dst;
1292 context->done_output = dst; 1607 context->done_output = dst;
1293 return; 1608 return;
1294 } 1609 }
1295 line &= 0xFF; 1610 line &= 0xFF;
1296 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); 1611 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context);
1297 uint8_t *sprite_buf, *plane_a, *plane_b; 1612 uint8_t *sprite_buf;
1613 uint8_t sprite, plane_a, plane_b;
1298 int plane_a_off, plane_b_off; 1614 int plane_a_off, plane_b_off;
1299 if (col) 1615 if (col)
1300 { 1616 {
1301 col-=2; 1617 col-=2;
1302 dst = context->output + BORDER_LEFT + col * 8; 1618 dst = context->output + BORDER_LEFT + col * 8;
1303 debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8; 1619 debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8;
1304 1620
1305 sprite_buf = context->linebuf + col * 8; 1621
1306 uint8_t a_src, src; 1622 uint8_t a_src, src;
1307 if (context->flags & FLAG_WINDOW) { 1623 if (context->flags & FLAG_WINDOW) {
1308 plane_a_off = context->buf_a_off; 1624 plane_a_off = context->buf_a_off;
1309 a_src = DBG_SRC_W; 1625 a_src = DBG_SRC_W;
1310 } else { 1626 } else {
1313 } 1629 }
1314 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF); 1630 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
1315 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); 1631 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
1316 1632
1317 if (context->regs[REG_MODE_4] & BIT_HILIGHT) { 1633 if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
1318 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 1634 if (output_disabled || test_layer) {
1319 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 1635 render_testreg_highlight(context, col, dst, debug_dst, plane_a_off, plane_b_off, output_disabled, test_layer);
1320 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 1636 } else {
1321 uint8_t pixel = context->regs[REG_BG_COLOR]; 1637 render_highlight(context, col, dst, debug_dst, plane_a_off, plane_b_off);
1322 uint32_t *colors = context->colors; 1638 }
1323 src = DBG_SRC_BG; 1639 } else {
1324 uint8_t intensity = 0; 1640 if (output_disabled || test_layer) {
1325 if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK) || i >= 8) { 1641 render_testreg(context, col, dst, debug_dst, plane_a_off, plane_b_off, output_disabled, test_layer);
1326 if (*plane_b & 0xF) { 1642 } else {
1327 pixel = *plane_b; 1643 render_normal(context, col, dst, debug_dst, plane_a_off, plane_b_off);
1328 src = DBG_SRC_B; 1644 }
1329 } 1645 }
1330 intensity = *plane_b & BUF_BIT_PRIORITY; 1646 dst += 16;
1331 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1332 pixel = *plane_a;
1333 src = a_src;
1334 }
1335 intensity |= *plane_a & BUF_BIT_PRIORITY;
1336 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1337 if ((*sprite_buf & 0x3F) == 0x3E) {
1338 intensity += BUF_BIT_PRIORITY;
1339 } else if ((*sprite_buf & 0x3F) == 0x3F) {
1340 intensity = 0;
1341 } else {
1342 pixel = *sprite_buf;
1343 src = DBG_SRC_S;
1344 if ((pixel & 0xF) == 0xE) {
1345 intensity = BUF_BIT_PRIORITY;
1346 } else {
1347 intensity |= pixel & BUF_BIT_PRIORITY;
1348 }
1349 }
1350 }
1351 }
1352 if (output_disabled) {
1353 pixel = 0x3F;
1354 }
1355 if (!intensity) {
1356 src |= DBG_SHADOW;
1357 colors += CRAM_SIZE;
1358 } else if (intensity == BUF_BIT_PRIORITY*2) {
1359 src |= DBG_HILIGHT;
1360 colors += CRAM_SIZE*2;
1361 }
1362 //TODO: Verify how test register stuff interacts with shadow/highlight
1363 //TODO: Simulate CRAM corruption from bus fight
1364 switch (test_layer)
1365 {
1366 case 1:
1367 pixel &= *sprite_buf;
1368 if (output_disabled && pixel) {
1369 src = DBG_SRC_S;
1370 }
1371 break;
1372 case 2:
1373 pixel &= *plane_a;
1374 if (output_disabled && pixel) {
1375 src = DBG_SRC_A;
1376 }
1377 break;
1378 case 3:
1379 pixel &= *plane_b;
1380 if (output_disabled && pixel) {
1381 src = DBG_SRC_B;
1382 }
1383 break;
1384 }
1385 *(debug_dst++) = src;
1386 *(dst++) = colors[pixel & 0x3F];
1387 }
1388 } else {
1389 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
1390 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
1391 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
1392 uint8_t pixel = context->regs[REG_BG_COLOR];
1393 src = DBG_SRC_BG;
1394 if (output_disabled) {
1395 pixel = 0x3F;
1396 } else {
1397 if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK) || i >= 8) {
1398 if (*plane_b & 0xF) {
1399 pixel = *plane_b;
1400 src = DBG_SRC_B;
1401 }
1402 if (*plane_a & 0xF && (*plane_a & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1403 pixel = *plane_a;
1404 src = a_src;
1405 }
1406 if (*sprite_buf & 0xF && (*sprite_buf & BUF_BIT_PRIORITY) >= (pixel & BUF_BIT_PRIORITY)) {
1407 pixel = *sprite_buf;
1408 src = DBG_SRC_S;
1409 }
1410 }
1411 }
1412 //TODO: Simulate CRAM corruption from bus fight
1413 switch (test_layer)
1414 {
1415 case 1:
1416 pixel &= *sprite_buf;
1417 if (output_disabled && pixel) {
1418 src = DBG_SRC_S;
1419 }
1420 break;
1421 case 2:
1422 pixel &= *plane_a;
1423 if (output_disabled && pixel) {
1424 src = DBG_SRC_A;
1425 }
1426 break;
1427 case 3:
1428 pixel &= *plane_b;
1429 if (output_disabled && pixel) {
1430 src = DBG_SRC_B;
1431 }
1432 break;
1433 }
1434 *(dst++) = context->colors[pixel & 0x3F];
1435 *(debug_dst++) = src;
1436 }
1437 }
1438 } else { 1647 } else {
1439 dst = context->output; 1648 dst = context->output;
1440 debug_dst = context->layer_debug_buf; 1649 debug_dst = context->layer_debug_buf;
1441 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; 1650 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1442 if (output_disabled) { 1651 if (output_disabled) {
1534 { 1743 {
1535 *dst = (pixels >> i & 0xF) | pal_priority; 1744 *dst = (pixels >> i & 0xF) | pal_priority;
1536 } 1745 }
1537 context->buf_a_off = (context->buf_a_off + 8) & 15; 1746 context->buf_a_off = (context->buf_a_off + 8) & 15;
1538 1747
1539 uint8_t bgcolor = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + CRAM_SIZE*3; 1748 uint8_t bgcolor = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET;
1540 uint32_t *dst = context->output + col * 8 + BORDER_LEFT; 1749 uint32_t *dst = context->output + col * 8 + BORDER_LEFT;
1541 uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT; 1750 uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT;
1542 if (context->state == PREPARING) { 1751 if (context->state == PREPARING) {
1543 for (int i = 0; i < 16; i++) 1752 for (int i = 0; i < 16; i++)
1544 { 1753 {
1556 for (int i = 0; i < 8; i++, sprite_src++) 1765 for (int i = 0; i < 8; i++, sprite_src++)
1557 { 1766 {
1558 uint8_t *bg_src = context->tmp_buf_a + ((8 + i + col * 8 - (context->hscroll_a & 0x7)) & 15); 1767 uint8_t *bg_src = context->tmp_buf_a + ((8 + i + col * 8 - (context->hscroll_a & 0x7)) & 15);
1559 if ((*bg_src & 0x4F) > 0x40 || !*sprite_src) { 1768 if ((*bg_src & 0x4F) > 0x40 || !*sprite_src) {
1560 //background plane has priority and is opaque or sprite layer is transparent 1769 //background plane has priority and is opaque or sprite layer is transparent
1561 *(dst++) = context->colors[(*bg_src & 0x1F) + CRAM_SIZE*3]; 1770 *(dst++) = context->colors[(*bg_src & 0x1F) + MODE4_OFFSET];
1562 *(debug_dst++) = DBG_SRC_A; 1771 *(debug_dst++) = DBG_SRC_A;
1563 } else { 1772 } else {
1564 //sprite layer is opaque and not covered by high priority BG pixels 1773 //sprite layer is opaque and not covered by high priority BG pixels
1565 *(dst++) = context->colors[*sprite_src | 0x10 + CRAM_SIZE*3]; 1774 *(dst++) = context->colors[*sprite_src | 0x10 + MODE4_OFFSET];
1566 *(debug_dst++) = DBG_SRC_S; 1775 *(debug_dst++) = DBG_SRC_S;
1567 } 1776 }
1568 } 1777 }
1569 } else { 1778 } else {
1570 for (int i = 0; i < 8; i++) 1779 for (int i = 0; i < 8; i++)
2179 fetch_sprite_cells_mode4(context);\ 2388 fetch_sprite_cells_mode4(context);\
2180 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 2))\ 2389 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 2))\
2181 case CALC_SLOT(slot, 3):\ 2390 case CALC_SLOT(slot, 3):\
2182 if ((slot + 3) == 140) {\ 2391 if ((slot + 3) == 140) {\
2183 uint32_t *dst = context->output + BORDER_LEFT + 256 + 8;\ 2392 uint32_t *dst = context->output + BORDER_LEFT + 256 + 8;\
2184 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + CRAM_SIZE*3];\ 2393 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];\
2185 for (int i = 0; i < BORDER_RIGHT-8; i++, dst++)\ 2394 for (int i = 0; i < BORDER_RIGHT-8; i++, dst++)\
2186 {\ 2395 {\
2187 *dst = bgcolor;\ 2396 *dst = bgcolor;\
2188 }\ 2397 }\
2189 context->done_output = dst;\ 2398 context->done_output = dst;\
2699 scan_sprite_table_mode4(context); 2908 scan_sprite_table_mode4(context);
2700 CHECK_LIMIT 2909 CHECK_LIMIT
2701 case 0: { 2910 case 0: {
2702 scan_sprite_table_mode4(context); 2911 scan_sprite_table_mode4(context);
2703 uint32_t *dst = context->output;; 2912 uint32_t *dst = context->output;;
2704 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + CRAM_SIZE*3]; 2913 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2705 for (int i = 0; i < BORDER_LEFT-8; i++, dst++) 2914 for (int i = 0; i < BORDER_LEFT-8; i++, dst++)
2706 { 2915 {
2707 *dst = bgcolor; 2916 *dst = bgcolor;
2708 } 2917 }
2709 context->done_output = dst; 2918 context->done_output = dst;
2721 case 4: { 2930 case 4: {
2722 scan_sprite_table_mode4(context); 2931 scan_sprite_table_mode4(context);
2723 context->buf_a_off = 8; 2932 context->buf_a_off = 8;
2724 memset(context->tmp_buf_a, 0, 8); 2933 memset(context->tmp_buf_a, 0, 8);
2725 uint32_t *dst = context->output + BORDER_LEFT - 8; 2934 uint32_t *dst = context->output + BORDER_LEFT - 8;
2726 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + CRAM_SIZE*3]; 2935 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2727 for (int i = 0; i < 8; i++, dst++) 2936 for (int i = 0; i < 8; i++, dst++)
2728 { 2937 {
2729 *dst = bgcolor; 2938 *dst = bgcolor;
2730 } 2939 }
2731 context->done_output = dst; 2940 context->done_output = dst;
2777 //set things up for sprite rendering in the next slot 2986 //set things up for sprite rendering in the next slot
2778 memset(context->linebuf, 0, LINEBUF_SIZE); 2987 memset(context->linebuf, 0, LINEBUF_SIZE);
2779 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1; 2988 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1;
2780 context->sprite_draws = MAX_DRAWS_H32_MODE4; 2989 context->sprite_draws = MAX_DRAWS_H32_MODE4;
2781 uint32_t *dst = context->output + BORDER_LEFT + 256; 2990 uint32_t *dst = context->output + BORDER_LEFT + 256;
2782 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + CRAM_SIZE*3]; 2991 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2783 for (int i = 0; i < 8; i++, dst++) 2992 for (int i = 0; i < 8; i++, dst++)
2784 { 2993 {
2785 *dst = bgcolor; 2994 *dst = bgcolor;
2786 } 2995 }
2787 context->done_output = dst; 2996 context->done_output = dst;
2992 3201
2993 if (dst) { 3202 if (dst) {
2994 if (mode_5) { 3203 if (mode_5) {
2995 bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 3204 bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2996 } else if (context->regs[REG_MODE_1] & BIT_MODE_4) { 3205 } else if (context->regs[REG_MODE_1] & BIT_MODE_4) {
2997 bg_color = context->colors[CRAM_SIZE * 3 + 0x10 + (context->regs[REG_BG_COLOR] & 0xF)]; 3206 bg_color = context->colors[MODE4_OFFSET + 0x10 + (context->regs[REG_BG_COLOR] & 0xF)];
2998 } 3207 }
2999 if (dst >= context->done_output) { 3208 if (dst >= context->done_output) {
3000 *(dst++) = bg_color; 3209 *(dst++) = bg_color;
3001 *(debug_dst++) = DBG_SRC_BG; 3210 *(debug_dst++) = DBG_SRC_BG;
3002 } else { 3211 } else {
3873 context->pending_vint_start = load_int32(buf); 4082 context->pending_vint_start = load_int32(buf);
3874 context->pending_hint_start = load_int32(buf); 4083 context->pending_hint_start = load_int32(buf);
3875 update_video_params(context); 4084 update_video_params(context);
3876 } 4085 }
3877 4086
4087 static vdp_context *current_vdp;
4088 static void vdp_debug_window_close(uint8_t which)
4089 {
4090 //TODO: remove need for current_vdp global, and find the VDP via current_system instead
4091 for (int i = 0; i < VDP_NUM_DEBUG_TYPES; i++)
4092 {
4093 if (current_vdp->enabled_debuggers & (1 << i) && which == current_vdp->debug_fb_indices[i]) {
4094 vdp_toggle_debug_view(current_vdp, i);
4095 break;
4096 }
4097 }
4098 }
4099
3878 void vdp_toggle_debug_view(vdp_context *context, uint8_t debug_type) 4100 void vdp_toggle_debug_view(vdp_context *context, uint8_t debug_type)
3879 { 4101 {
3880 if (context->enabled_debuggers & 1 << debug_type) { 4102 if (context->enabled_debuggers & 1 << debug_type) {
3881 render_destroy_window(context->debug_fb_indices[debug_type]); 4103 render_destroy_window(context->debug_fb_indices[debug_type]);
3882 context->enabled_debuggers &= ~(1 << debug_type); 4104 context->enabled_debuggers &= ~(1 << debug_type);
3908 fetch_immediately = 1; 4130 fetch_immediately = 1;
3909 break; 4131 break;
3910 default: 4132 default:
3911 return; 4133 return;
3912 } 4134 }
3913 context->debug_fb_indices[debug_type] = render_create_window(caption, width, height); 4135 current_vdp = context;
4136 context->debug_fb_indices[debug_type] = render_create_window(caption, width, height, vdp_debug_window_close);
3914 if (context->debug_fb_indices[debug_type]) { 4137 if (context->debug_fb_indices[debug_type]) {
3915 context->enabled_debuggers |= 1 << debug_type; 4138 context->enabled_debuggers |= 1 << debug_type;
3916 } 4139 }
3917 if (fetch_immediately) { 4140 if (fetch_immediately) {
3918 context->debug_fbs[debug_type] = render_get_framebuffer(context->debug_fb_indices[debug_type], &context->debug_fb_pitch[debug_type]); 4141 context->debug_fbs[debug_type] = render_get_framebuffer(context->debug_fb_indices[debug_type], &context->debug_fb_pitch[debug_type]);