comparison vdp.c @ 1842:49f65d240299 mame_interp

Merge from default
author Michael Pavone <pavone@retrodev.com>
date Sun, 14 Apr 2019 23:38:02 -0700
parents 304d47a5c67f
children 84f16a804ce5
comparison
equal deleted inserted replaced
1787:0c6d07f91346 1842:49f65d240299
48 #define BORDER_BOT_V24 24 48 #define BORDER_BOT_V24 24
49 #define BORDER_BOT_V28 8 49 #define BORDER_BOT_V28 8
50 #define BORDER_BOT_V24_PAL 48 50 #define BORDER_BOT_V24_PAL 48
51 #define BORDER_BOT_V28_PAL 32 51 #define BORDER_BOT_V28_PAL 32
52 #define BORDER_BOT_V30_PAL 24 52 #define BORDER_BOT_V30_PAL 24
53
54 #define INVALID_LINE (PAL_INACTIVE_START+BORDER_TOP_V30_PAL+BORDER_BOT_V30_PAL)
55 53
56 enum { 54 enum {
57 INACTIVE = 0, 55 INACTIVE = 0,
58 PREPARING, //used for line 0x1FF 56 PREPARING, //used for line 0x1FF
59 ACTIVE 57 ACTIVE
1326 } 1324 }
1327 *debug_dst = src; 1325 *debug_dst = src;
1328 return (sh_pixel){.index = pixel, .intensity = intensity}; 1326 return (sh_pixel){.index = pixel, .intensity = intensity};
1329 } 1327 }
1330 1328
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) 1329 static void render_normal(vdp_context *context, int32_t col, uint8_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
1332 { 1330 {
1333 int start = 0; 1331 int start = 0;
1334 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) { 1332 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1335 uint32_t bgcolor = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 1333 memset(dst, 0, 8);
1336 for (int i = 0; i < 8; ++i) 1334 memset(debug_dst, DBG_SRC_BG, 8);
1337 { 1335 dst += 8;
1338 *(dst++) = bgcolor; 1336 debug_dst += 8;
1339 *(debug_dst++) = DBG_SRC_BG;
1340 }
1341 start = 8; 1337 start = 8;
1342 } 1338 }
1343 uint8_t *sprite_buf = context->linebuf + col * 8 + start; 1339 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) 1340 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1345 { 1341 {
1346 uint8_t sprite, plane_a, plane_b; 1342 uint8_t sprite, plane_a, plane_b;
1347 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK]; 1343 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]; 1344 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1349 sprite = *sprite_buf; 1345 sprite = *sprite_buf;
1350 uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]); 1346 *(dst++) = composite_normal(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]) & 0x3F;
1351 debug_dst++; 1347 debug_dst++;
1352 *(dst++) = context->colors[pixel & 0x3F]; 1348 }
1353 } 1349 }
1354 } 1350
1355 1351 static void render_highlight(vdp_context *context, int32_t col, uint8_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off)
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 { 1352 {
1358 int start = 0; 1353 int start = 0;
1359 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) { 1354 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1360 uint32_t bgcolor = context->colors[SHADOW_OFFSET + (context->regs[REG_BG_COLOR] & 0x3F)]; 1355 memset(dst, SHADOW_OFFSET + (context->regs[REG_BG_COLOR] & 0x3F), 8);
1361 for (int i = 0; i < 8; ++i) 1356 memset(debug_dst, DBG_SRC_BG | DBG_SHADOW, 8);
1362 { 1357 dst += 8;
1363 *(dst++) = bgcolor; 1358 debug_dst += 8;
1364 *(debug_dst++) = DBG_SRC_BG | DBG_SHADOW;
1365 }
1366 start = 8; 1359 start = 8;
1367 } 1360 }
1368 uint8_t *sprite_buf = context->linebuf + col * 8 + start; 1361 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) 1362 for (int i = start; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i)
1370 { 1363 {
1371 uint8_t sprite, plane_a, plane_b; 1364 uint8_t sprite, plane_a, plane_b;
1372 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK]; 1365 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]; 1366 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1374 sprite = *sprite_buf; 1367 sprite = *sprite_buf;
1375 sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]); 1368 sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, context->regs[REG_BG_COLOR]);
1376 uint32_t *colors; 1369 uint8_t final_pixel;
1377 if (pixel.intensity == BUF_BIT_PRIORITY << 1) { 1370 if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1378 colors = context->colors + HIGHLIGHT_OFFSET; 1371 final_pixel = (pixel.index & 0x3F) + HIGHLIGHT_OFFSET;
1379 } else if (pixel.intensity) { 1372 } else if (pixel.intensity) {
1380 colors = context->colors; 1373 final_pixel = pixel.index & 0x3F;
1381 } else { 1374 } else {
1382 colors = context->colors + SHADOW_OFFSET; 1375 final_pixel = (pixel.index & 0x3F) + SHADOW_OFFSET;
1383 } 1376 }
1384 debug_dst++; 1377 debug_dst++;
1385 *(dst++) = colors[pixel.index & 0x3F]; 1378 *(dst++) = final_pixel;
1386 } 1379 }
1387 } 1380 }
1388 1381
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) 1382 static void render_testreg(vdp_context *context, int32_t col, uint8_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1390 { 1383 {
1391 if (output_disabled) { 1384 if (output_disabled) {
1392 switch (test_layer) 1385 switch (test_layer)
1393 { 1386 {
1394 case 0: 1387 case 0:
1400 break; 1393 break;
1401 case 1: { 1394 case 1: {
1402 uint8_t *sprite_buf = context->linebuf + col * 8; 1395 uint8_t *sprite_buf = context->linebuf + col * 8;
1403 for (int i = 0; i < 16; i++) 1396 for (int i = 0; i < 16; i++)
1404 { 1397 {
1405 *(dst++) = context->colors[*(sprite_buf++) & 0x3F]; 1398 *(dst++) = *(sprite_buf++) & 0x3F;
1406 *(debug_dst++) = DBG_SRC_S; 1399 *(debug_dst++) = DBG_SRC_S;
1407 } 1400 }
1408 break; 1401 break;
1409 } 1402 }
1410 case 2: 1403 case 2:
1411 for (int i = 0; i < 16; i++) 1404 for (int i = 0; i < 16; i++)
1412 { 1405 {
1413 *(dst++) = context->colors[context->tmp_buf_a[(plane_a_off++) & SCROLL_BUFFER_MASK] & 0x3F]; 1406 *(dst++) = context->tmp_buf_a[(plane_a_off++) & SCROLL_BUFFER_MASK] & 0x3F;
1414 *(debug_dst++) = DBG_SRC_A; 1407 *(debug_dst++) = DBG_SRC_A;
1415 } 1408 }
1416 break; 1409 break;
1417 case 3: 1410 case 3:
1418 for (int i = 0; i < 16; i++) 1411 for (int i = 0; i < 16; i++)
1419 { 1412 {
1420 *(dst++) = context->colors[context->tmp_buf_b[(plane_b_off++) & SCROLL_BUFFER_MASK] & 0x3F]; 1413 *(dst++) = context->tmp_buf_b[(plane_b_off++) & SCROLL_BUFFER_MASK] & 0x3F;
1421 *(debug_dst++) = DBG_SRC_B; 1414 *(debug_dst++) = DBG_SRC_B;
1422 } 1415 }
1423 break; 1416 break;
1424 } 1417 }
1425 } else { 1418 } else {
1426 int start = 0; 1419 int start = 0;
1427 uint8_t *sprite_buf = context->linebuf + col * 8; 1420 uint8_t *sprite_buf = context->linebuf + col * 8;
1428 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) { 1421 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1429 //TODO: Confirm how test register interacts with column 0 blanking 1422 //TODO: Confirm how test register interacts with column 0 blanking
1430 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; 1423 uint8_t pixel = 0x3F;
1431 uint8_t src = DBG_SRC_BG; 1424 uint8_t src = DBG_SRC_BG;
1432 for (int i = 0; i < 8; ++i) 1425 for (int i = 0; i < 8; ++i)
1433 { 1426 {
1434 switch (test_layer) 1427 switch (test_layer)
1435 { 1428 {
1451 src = DBG_SRC_B; 1444 src = DBG_SRC_B;
1452 } 1445 }
1453 break; 1446 break;
1454 } 1447 }
1455 1448
1456 *(dst++) = context->colors[pixel & 0x3F]; 1449 *(dst++) = pixel;
1457 *(debug_dst++) = src; 1450 *(debug_dst++) = src;
1458 } 1451 }
1459 plane_a_off += 8; 1452 plane_a_off += 8;
1460 plane_b_off += 8; 1453 plane_b_off += 8;
1461 sprite_buf += 8; 1454 sprite_buf += 8;
1465 { 1458 {
1466 uint8_t sprite, plane_a, plane_b; 1459 uint8_t sprite, plane_a, plane_b;
1467 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK]; 1460 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]; 1461 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1469 sprite = *sprite_buf; 1462 sprite = *sprite_buf;
1470 uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, 0x3F); 1463 uint8_t pixel = composite_normal(context, debug_dst, sprite, plane_a, plane_b, 0x3F) & 0x3F;
1471 switch (test_layer) 1464 switch (test_layer)
1472 { 1465 {
1473 case 1: 1466 case 1:
1474 pixel &= sprite; 1467 pixel &= sprite;
1475 if (pixel) { 1468 if (pixel) {
1488 *debug_dst = DBG_SRC_B; 1481 *debug_dst = DBG_SRC_B;
1489 } 1482 }
1490 break; 1483 break;
1491 } 1484 }
1492 debug_dst++; 1485 debug_dst++;
1493 *(dst++) = context->colors[pixel & 0x3F]; 1486 *(dst++) = pixel;
1494 } 1487 }
1495 } 1488 }
1496 } 1489 }
1497 1490
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) 1491 static void render_testreg_highlight(vdp_context *context, int32_t col, uint8_t *dst, uint8_t *debug_dst, int plane_a_off, int plane_b_off, uint8_t output_disabled, uint8_t test_layer)
1499 { 1492 {
1500 int start = 0; 1493 int start = 0;
1501 uint8_t *sprite_buf = context->linebuf + col * 8; 1494 uint8_t *sprite_buf = context->linebuf + col * 8;
1502 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) { 1495 if (!col && (context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1503 //TODO: Confirm how test register interacts with column 0 blanking 1496 //TODO: Confirm how test register interacts with column 0 blanking
1504 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; 1497 uint8_t pixel = 0x3F;
1505 uint8_t src = DBG_SRC_BG | DBG_SHADOW; 1498 uint8_t src = DBG_SRC_BG | DBG_SHADOW;
1506 for (int i = 0; i < 8; ++i) 1499 for (int i = 0; i < 8; ++i)
1507 { 1500 {
1508 switch (test_layer) 1501 switch (test_layer)
1509 { 1502 {
1525 src = DBG_SRC_B | DBG_SHADOW; 1518 src = DBG_SRC_B | DBG_SHADOW;
1526 } 1519 }
1527 break; 1520 break;
1528 } 1521 }
1529 1522
1530 *(dst++) = context->colors[SHADOW_OFFSET + (pixel & 0x3F)]; 1523 *(dst++) = SHADOW_OFFSET + pixel;
1531 *(debug_dst++) = src; 1524 *(debug_dst++) = src;
1532 } 1525 }
1533 plane_a_off += 8; 1526 plane_a_off += 8;
1534 plane_b_off += 8; 1527 plane_b_off += 8;
1535 sprite_buf += 8; 1528 sprite_buf += 8;
1540 uint8_t sprite, plane_a, plane_b; 1533 uint8_t sprite, plane_a, plane_b;
1541 plane_a = context->tmp_buf_a[plane_a_off & SCROLL_BUFFER_MASK]; 1534 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]; 1535 plane_b = context->tmp_buf_b[plane_b_off & SCROLL_BUFFER_MASK];
1543 sprite = *sprite_buf; 1536 sprite = *sprite_buf;
1544 sh_pixel pixel = composite_highlight(context, debug_dst, sprite, plane_a, plane_b, 0x3F); 1537 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) { 1538 if (output_disabled) {
1554 pixel.index = 0x3F; 1539 pixel.index = 0x3F;
1540 } else {
1541 pixel.index &= 0x3F;
1555 } 1542 }
1556 switch (test_layer) 1543 switch (test_layer)
1557 { 1544 {
1558 case 1: 1545 case 1:
1559 pixel.index &= sprite; 1546 pixel.index &= sprite;
1572 if (pixel.index) { 1559 if (pixel.index) {
1573 *debug_dst = DBG_SRC_B; 1560 *debug_dst = DBG_SRC_B;
1574 } 1561 }
1575 break; 1562 break;
1576 } 1563 }
1564 if (pixel.intensity == BUF_BIT_PRIORITY << 1) {
1565 pixel.index += HIGHLIGHT_OFFSET;
1566 } else if (!pixel.intensity) {
1567 pixel.index += SHADOW_OFFSET;
1568 }
1577 debug_dst++; 1569 debug_dst++;
1578 *(dst++) = colors[pixel.index & 0x3F]; 1570 *(dst++) = pixel.index;
1579 } 1571 }
1580 } 1572 }
1581 1573
1582 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) 1574 static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
1583 { 1575 {
1584 uint32_t *dst; 1576 uint8_t *dst;
1585 uint8_t *debug_dst; 1577 uint8_t *debug_dst;
1586 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0; 1578 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
1587 uint8_t test_layer = context->test_port >> 7 & 3; 1579 uint8_t test_layer = context->test_port >> 7 & 3;
1588 if (context->state == PREPARING && !test_layer) { 1580 if (context->state == PREPARING && !test_layer) {
1589 if (col) { 1581 if (col) {
1590 col -= 2; 1582 col -= 2;
1591 dst = context->output + BORDER_LEFT + col * 8; 1583 dst = context->compositebuf + BORDER_LEFT + col * 8;
1592 } else { 1584 } else {
1593 dst = context->output; 1585 dst = context->compositebuf;
1594 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 1586 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1595 for (int i = 0; i < BORDER_LEFT; i++, dst++) 1587 memset(dst, 0, BORDER_LEFT);
1596 { 1588 context->done_composite = dst + BORDER_LEFT;
1597 *dst = bg_color;
1598 }
1599 context->done_output = dst;
1600 return; 1589 return;
1601 } 1590 }
1602 uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 1591 memset(dst, 0, 16);
1603 for (int i = 0; i < 16; i++) 1592 context->done_composite = dst + 16;
1604 {
1605 *(dst++) = color;
1606 }
1607 context->done_output = dst;
1608 return; 1593 return;
1609 } 1594 }
1610 line &= 0xFF; 1595 line &= 0xFF;
1611 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); 1596 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context);
1612 uint8_t *sprite_buf; 1597 uint8_t *sprite_buf;
1613 uint8_t sprite, plane_a, plane_b; 1598 uint8_t sprite, plane_a, plane_b;
1614 int plane_a_off, plane_b_off; 1599 int plane_a_off, plane_b_off;
1615 if (col) 1600 if (col)
1616 { 1601 {
1617 col-=2; 1602 col-=2;
1618 dst = context->output + BORDER_LEFT + col * 8; 1603 dst = context->compositebuf + BORDER_LEFT + col * 8;
1619 debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8; 1604 debug_dst = context->layer_debug_buf + BORDER_LEFT + col * 8;
1620 1605
1621 1606
1622 uint8_t a_src, src; 1607 uint8_t a_src, src;
1623 if (context->flags & FLAG_WINDOW) { 1608 if (context->flags & FLAG_WINDOW) {
1643 render_normal(context, col, dst, debug_dst, plane_a_off, plane_b_off); 1628 render_normal(context, col, dst, debug_dst, plane_a_off, plane_b_off);
1644 } 1629 }
1645 } 1630 }
1646 dst += 16; 1631 dst += 16;
1647 } else { 1632 } else {
1648 dst = context->output; 1633 dst = context->compositebuf;
1649 debug_dst = context->layer_debug_buf; 1634 debug_dst = context->layer_debug_buf;
1650 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; 1635 uint8_t pixel = 0;
1651 if (output_disabled) { 1636 if (output_disabled) {
1652 pixel = 0x3F; 1637 pixel = 0x3F;
1653 } 1638 }
1654 uint32_t bg_color = context->colors[pixel];
1655 if (test_layer) { 1639 if (test_layer) {
1656 switch(test_layer) 1640 switch(test_layer)
1657 { 1641 {
1658 case 1: 1642 case 1:
1659 bg_color = context->colors[0]; 1643 memset(dst, 0, BORDER_LEFT);
1660 for (int i = 0; i < BORDER_LEFT; i++, dst++, debug_dst++) 1644 memset(debug_dst, DBG_SRC_BG, BORDER_LEFT);
1661 {
1662 *dst = bg_color;
1663 *debug_dst = DBG_SRC_BG;
1664
1665 }
1666 break; 1645 break;
1667 case 2: { 1646 case 2: {
1668 //plane A 1647 //plane A
1669 //TODO: Deal with Window layer 1648 //TODO: Deal with Window layer
1670 int i; 1649 int i;
1671 i = 0; 1650 i = 0;
1672 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT); 1651 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT);
1673 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 1652 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
1674 for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++) 1653 for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
1675 { 1654 {
1676 *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK]]; 1655 *dst = context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK];
1677 *debug_dst = DBG_SRC_A; 1656 *debug_dst = DBG_SRC_A;
1678 } 1657 }
1679 break; 1658 break;
1680 } 1659 }
1681 case 3: { 1660 case 3: {
1684 i = 0; 1663 i = 0;
1685 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT); 1664 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT);
1686 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 1665 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
1687 for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++) 1666 for (; i < BORDER_LEFT; buf_off++, i++, dst++, debug_dst++)
1688 { 1667 {
1689 *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK]]; 1668 *dst = context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK];
1690 *debug_dst = DBG_SRC_B; 1669 *debug_dst = DBG_SRC_B;
1691 } 1670 }
1692 break; 1671 break;
1693 } 1672 }
1694 } 1673 }
1695 } else { 1674 } else {
1696 for (int i = 0; i < BORDER_LEFT; i++, dst++, debug_dst++) 1675 memset(dst, pixel, BORDER_LEFT);
1697 { 1676 memset(debug_dst, DBG_SRC_BG, BORDER_LEFT);
1698 *dst = bg_color; 1677 }
1699 *debug_dst = DBG_SRC_BG; 1678 dst += BORDER_LEFT;
1700 } 1679 }
1701 } 1680 context->done_composite = dst;
1702 }
1703 context->done_output = dst;
1704 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 1681 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1705 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 1682 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1706 } 1683 }
1707 1684
1708 static void render_map_mode4(uint32_t line, int32_t col, vdp_context * context) 1685 static void render_map_mode4(uint32_t line, int32_t col, vdp_context * context)
1743 { 1720 {
1744 *dst = (pixels >> i & 0xF) | pal_priority; 1721 *dst = (pixels >> i & 0xF) | pal_priority;
1745 } 1722 }
1746 context->buf_a_off = (context->buf_a_off + 8) & 15; 1723 context->buf_a_off = (context->buf_a_off + 8) & 15;
1747 1724
1748 uint8_t bgcolor = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET; 1725 uint8_t *dst = context->compositebuf + col * 8 + BORDER_LEFT;
1749 uint32_t *dst = context->output + col * 8 + BORDER_LEFT;
1750 uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT; 1726 uint8_t *debug_dst = context->layer_debug_buf + col * 8 + BORDER_LEFT;
1751 if (context->state == PREPARING) { 1727 if (context->state == PREPARING) {
1752 for (int i = 0; i < 16; i++) 1728 memset(dst, 0, 8);
1753 { 1729 memset(debug_dst, DBG_SRC_BG, 8);
1754 *(dst++) = context->colors[bgcolor]; 1730 context->done_composite = dst + 8;
1755 }
1756 context->done_output = dst;
1757 return; 1731 return;
1758 } 1732 }
1759 1733
1760 if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK)) { 1734 if (col || !(context->regs[REG_MODE_1] & BIT_COL0_MASK)) {
1761 uint8_t *sprite_src = context->linebuf + col * 8; 1735 uint8_t *sprite_src = context->linebuf + col * 8;
1765 for (int i = 0; i < 8; i++, sprite_src++) 1739 for (int i = 0; i < 8; i++, sprite_src++)
1766 { 1740 {
1767 uint8_t *bg_src = context->tmp_buf_a + ((8 + i + col * 8 - (context->hscroll_a & 0x7)) & 15); 1741 uint8_t *bg_src = context->tmp_buf_a + ((8 + i + col * 8 - (context->hscroll_a & 0x7)) & 15);
1768 if ((*bg_src & 0x4F) > 0x40 || !*sprite_src) { 1742 if ((*bg_src & 0x4F) > 0x40 || !*sprite_src) {
1769 //background plane has priority and is opaque or sprite layer is transparent 1743 //background plane has priority and is opaque or sprite layer is transparent
1770 *(dst++) = context->colors[(*bg_src & 0x1F) + MODE4_OFFSET]; 1744 uint8_t pixel = *bg_src & 0x1F;
1771 *(debug_dst++) = DBG_SRC_A; 1745 *(dst++) = pixel + MODE4_OFFSET;
1746 *(debug_dst++) = pixel ? DBG_SRC_A : DBG_SRC_BG;
1772 } else { 1747 } else {
1773 //sprite layer is opaque and not covered by high priority BG pixels 1748 //sprite layer is opaque and not covered by high priority BG pixels
1774 *(dst++) = context->colors[*sprite_src | 0x10 + MODE4_OFFSET]; 1749 *(dst++) = (*sprite_src | 0x10) + MODE4_OFFSET;
1775 *(debug_dst++) = DBG_SRC_S; 1750 *(debug_dst++) = DBG_SRC_S;
1776 } 1751 }
1777 } 1752 }
1778 } else { 1753 context->done_composite = dst;
1779 for (int i = 0; i < 8; i++) 1754 } else {
1780 { 1755 memset(dst, 0, 8);
1781 *(dst++) = context->colors[bgcolor]; 1756 memset(dst, DBG_SRC_BG, 8);
1782 *(debug_dst++) = DBG_SRC_BG; 1757 context->done_composite = dst + 8;
1783 } 1758 }
1784 }
1785 context->done_output = dst;
1786 } 1759 }
1787 1760
1788 static uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19}; 1761 static uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19};
1789 1762
1790 static void vdp_advance_line(vdp_context *context) 1763 static void vdp_advance_line(vdp_context *context)
2098 //potential screen rolling if the mode is changed at an inopportune time 2071 //potential screen rolling if the mode is changed at an inopportune time
2099 context->output_lines = 0; 2072 context->output_lines = 0;
2100 } 2073 }
2101 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); 2074 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top);
2102 } else { 2075 } else {
2103 output_line = INVALID_LINE; 2076 context->output = NULL;
2104 } 2077 }
2105 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); 2078 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line);
2106 context->done_output = context->output;
2107 #ifdef DEBUG_FB_FILL 2079 #ifdef DEBUG_FB_FILL
2108 for (int i = 0; i < LINEBUF_SIZE; i++) 2080 for (int i = 0; i < LINEBUF_SIZE; i++)
2109 { 2081 {
2110 context->output[i] = 0xFFFF00FF; 2082 context->output[i] = 0xFFFF00FF;
2111 } 2083 }
2112 #endif 2084 #endif
2113 if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) { 2085 if (context->output && (context->regs[REG_MODE_4] & BIT_H40)) {
2114 context->h40_lines++; 2086 context->h40_lines++;
2115 } 2087 }
2116 } 2088 }
2117 } 2089 }
2118 2090
2129 ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL 2101 ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL
2130 : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; 2102 : 224 + BORDER_TOP_V28 + BORDER_BOT_V28;
2131 if (context->output_lines <= lines_max && context->output_lines > 0) { 2103 if (context->output_lines <= lines_max && context->output_lines > 0) {
2132 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1)); 2104 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * (context->output_lines - 1));
2133 } else { 2105 } else {
2134 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * INVALID_LINE); 2106 context->output = NULL;
2135 } 2107 }
2136 } 2108 }
2137 2109
2138 static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col) 2110 static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col)
2139 { 2111 {
2146 } 2118 }
2147 } 2119 }
2148 2120
2149 static void draw_right_border(vdp_context *context) 2121 static void draw_right_border(vdp_context *context)
2150 { 2122 {
2151 uint32_t *dst = context->output + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256); 2123 uint8_t *dst = context->compositebuf + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256);
2152 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F; 2124 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
2153 if ((context->test_port & TEST_BIT_DISABLE) != 0) { 2125 if ((context->test_port & TEST_BIT_DISABLE) != 0) {
2154 pixel = 0x3F; 2126 pixel = 0x3F;
2155 } 2127 }
2156 uint32_t bg_color = context->colors[pixel];
2157 uint8_t test_layer = context->test_port >> 7 & 3; 2128 uint8_t test_layer = context->test_port >> 7 & 3;
2158 if (test_layer) { 2129 if (test_layer) {
2159 switch(test_layer) 2130 switch(test_layer)
2160 { 2131 {
2161 case 1: 2132 case 1:
2162 bg_color = context->colors[0]; 2133 memset(dst, 0, BORDER_RIGHT);
2163 for (int i = 0; i < BORDER_RIGHT; i++, dst++) 2134 dst += BORDER_RIGHT;
2164 {
2165 *dst = bg_color;
2166 }
2167 break; 2135 break;
2168 case 2: { 2136 case 2: {
2169 //plane A 2137 //plane A
2170 //TODO: Deal with Window layer 2138 //TODO: Deal with Window layer
2171 int i; 2139 int i;
2172 i = 0; 2140 i = 0;
2173 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF); 2141 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF);
2174 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK); 2142 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
2175 for (; i < BORDER_RIGHT; buf_off++, i++, dst++) 2143 for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
2176 { 2144 {
2177 *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F]; 2145 *dst = context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F;
2178 } 2146 }
2179 break; 2147 break;
2180 } 2148 }
2181 case 3: { 2149 case 3: {
2182 //plane B 2150 //plane B
2184 i = 0; 2152 i = 0;
2185 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF); 2153 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF);
2186 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK); 2154 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
2187 for (; i < BORDER_RIGHT; buf_off++, i++, dst++) 2155 for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
2188 { 2156 {
2189 *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F]; 2157 *dst = context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F;
2190 } 2158 }
2191 break; 2159 break;
2192 } 2160 }
2193 } 2161 }
2194 } else { 2162 } else {
2195 for (int i = 0; i < BORDER_RIGHT; i++, dst++) 2163 memset(dst, 0, BORDER_RIGHT);
2196 { 2164 dst += BORDER_RIGHT;
2197 *dst = bg_color; 2165 }
2198 } 2166 context->done_composite = dst;
2199 }
2200 context->done_output = dst;
2201 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 2167 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2202 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 2168 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
2203 } 2169 }
2204 2170
2205 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; } 2171 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; }
2206 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY 2172 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
2173 #define OUTPUT_PIXEL(slot) if ((slot) >= BG_START_SLOT) {\
2174 uint8_t *src = context->compositebuf + ((slot) - BG_START_SLOT) *2;\
2175 uint32_t *dst = context->output + ((slot) - BG_START_SLOT) *2;\
2176 if ((*src & 0x3F) | test_layer) {\
2177 *(dst++) = context->colors[*(src++)];\
2178 } else {\
2179 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2180 }\
2181 if ((*src & 0x3F) | test_layer) {\
2182 *(dst++) = context->colors[*(src++)];\
2183 } else {\
2184 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2185 }\
2186 }
2187
2188 #define OUTPUT_PIXEL_H40(slot) if (slot <= (BG_START_SLOT + LINEBUF_SIZE/2)) {\
2189 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\
2190 uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\
2191 if ((*src & 0x3F) | test_layer) {\
2192 *(dst++) = context->colors[*(src++)];\
2193 } else {\
2194 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2195 }\
2196 if (slot != (BG_START_SLOT + LINEBUF_SIZE/2)) {\
2197 if ((*src & 0x3F) | test_layer) {\
2198 *(dst++) = context->colors[*(src++)];\
2199 } else {\
2200 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2201 }\
2202 }\
2203 }
2204
2205 #define OUTPUT_PIXEL_H32(slot) if (slot <= (BG_START_SLOT + (256+HORIZ_BORDER)/2)) {\
2206 uint8_t *src = context->compositebuf + (slot - BG_START_SLOT) *2;\
2207 uint32_t *dst = context->output + (slot - BG_START_SLOT) *2;\
2208 if ((*src & 0x3F) | test_layer) {\
2209 *(dst++) = context->colors[*(src++)];\
2210 } else {\
2211 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2212 }\
2213 if (slot != (BG_START_SLOT + (256+HORIZ_BORDER)/2)) {\
2214 if ((*src & 0x3F) | test_layer) {\
2215 *(dst++) = context->colors[*(src++)];\
2216 } else {\
2217 *(dst++) = context->colors[(*(src++) & 0xC0) | bgindex];\
2218 }\
2219 }\
2220 }
2207 2221
2208 #define COLUMN_RENDER_BLOCK(column, startcyc) \ 2222 #define COLUMN_RENDER_BLOCK(column, startcyc) \
2209 case startcyc:\ 2223 case startcyc:\
2224 OUTPUT_PIXEL(startcyc)\
2210 read_map_scroll_a(column, context->vcounter, context);\ 2225 read_map_scroll_a(column, context->vcounter, context);\
2211 CHECK_LIMIT\ 2226 CHECK_LIMIT\
2212 case ((startcyc+1)&0xFF):\ 2227 case ((startcyc+1)&0xFF):\
2228 OUTPUT_PIXEL((startcyc+1)&0xFF)\
2213 external_slot(context);\ 2229 external_slot(context);\
2214 CHECK_LIMIT\ 2230 CHECK_LIMIT\
2215 case ((startcyc+2)&0xFF):\ 2231 case ((startcyc+2)&0xFF):\
2232 OUTPUT_PIXEL((startcyc+2)&0xFF)\
2216 render_map_1(context);\ 2233 render_map_1(context);\
2217 CHECK_LIMIT\ 2234 CHECK_LIMIT\
2218 case ((startcyc+3)&0xFF):\ 2235 case ((startcyc+3)&0xFF):\
2236 OUTPUT_PIXEL((startcyc+3)&0xFF)\
2219 render_map_2(context);\ 2237 render_map_2(context);\
2220 CHECK_LIMIT\ 2238 CHECK_LIMIT\
2221 case ((startcyc+4)&0xFF):\ 2239 case ((startcyc+4)&0xFF):\
2240 OUTPUT_PIXEL((startcyc+4)&0xFF)\
2222 read_map_scroll_b(column, context->vcounter, context);\ 2241 read_map_scroll_b(column, context->vcounter, context);\
2223 CHECK_LIMIT\ 2242 CHECK_LIMIT\
2224 case ((startcyc+5)&0xFF):\ 2243 case ((startcyc+5)&0xFF):\
2244 OUTPUT_PIXEL((startcyc+5)&0xFF)\
2225 read_sprite_x(context->vcounter, context);\ 2245 read_sprite_x(context->vcounter, context);\
2226 CHECK_LIMIT\ 2246 CHECK_LIMIT\
2227 case ((startcyc+6)&0xFF):\ 2247 case ((startcyc+6)&0xFF):\
2248 OUTPUT_PIXEL((startcyc+6)&0xFF)\
2228 render_map_3(context);\ 2249 render_map_3(context);\
2229 CHECK_LIMIT\ 2250 CHECK_LIMIT\
2230 case ((startcyc+7)&0xFF):\ 2251 case ((startcyc+7)&0xFF):\
2252 OUTPUT_PIXEL((startcyc+7)&0xFF)\
2231 render_map_output(context->vcounter, column, context);\ 2253 render_map_output(context->vcounter, column, context);\
2232 CHECK_LIMIT 2254 CHECK_LIMIT
2233 2255
2234 #define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \ 2256 #define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \
2235 case startcyc:\ 2257 case startcyc:\
2258 OUTPUT_PIXEL(startcyc)\
2236 read_map_scroll_a(column, context->vcounter, context);\ 2259 read_map_scroll_a(column, context->vcounter, context);\
2237 CHECK_LIMIT\ 2260 CHECK_LIMIT\
2238 case (startcyc+1):\ 2261 case (startcyc+1):\
2239 /* refresh, no don't run dma src */\ 2262 /* refresh, so don't run dma src */\
2263 OUTPUT_PIXEL((startcyc+1)&0xFF)\
2240 context->hslot++;\ 2264 context->hslot++;\
2241 context->cycles += slot_cycles;\ 2265 context->cycles += slot_cycles;\
2242 CHECK_ONLY\ 2266 CHECK_ONLY\
2243 case (startcyc+2):\ 2267 case (startcyc+2):\
2268 OUTPUT_PIXEL((startcyc+2)&0xFF)\
2244 render_map_1(context);\ 2269 render_map_1(context);\
2245 CHECK_LIMIT\ 2270 CHECK_LIMIT\
2246 case (startcyc+3):\ 2271 case (startcyc+3):\
2272 OUTPUT_PIXEL((startcyc+3)&0xFF)\
2247 render_map_2(context);\ 2273 render_map_2(context);\
2248 CHECK_LIMIT\ 2274 CHECK_LIMIT\
2249 case (startcyc+4):\ 2275 case (startcyc+4):\
2276 OUTPUT_PIXEL((startcyc+4)&0xFF)\
2250 read_map_scroll_b(column, context->vcounter, context);\ 2277 read_map_scroll_b(column, context->vcounter, context);\
2251 CHECK_LIMIT\ 2278 CHECK_LIMIT\
2252 case (startcyc+5):\ 2279 case (startcyc+5):\
2280 OUTPUT_PIXEL((startcyc+5)&0xFF)\
2253 read_sprite_x(context->vcounter, context);\ 2281 read_sprite_x(context->vcounter, context);\
2254 CHECK_LIMIT\ 2282 CHECK_LIMIT\
2255 case (startcyc+6):\ 2283 case (startcyc+6):\
2284 OUTPUT_PIXEL((startcyc+6)&0xFF)\
2256 render_map_3(context);\ 2285 render_map_3(context);\
2257 CHECK_LIMIT\ 2286 CHECK_LIMIT\
2258 case (startcyc+7):\ 2287 case (startcyc+7):\
2288 OUTPUT_PIXEL((startcyc+7)&0xFF)\
2259 render_map_output(context->vcounter, column, context);\ 2289 render_map_output(context->vcounter, column, context);\
2260 CHECK_LIMIT 2290 CHECK_LIMIT
2261 2291
2262 #define COLUMN_RENDER_BLOCK_MODE4(column, startcyc) \ 2292 #define COLUMN_RENDER_BLOCK_MODE4(column, startcyc) \
2263 case startcyc:\ 2293 case startcyc:\
2294 OUTPUT_PIXEL(startcyc)\
2264 read_map_mode4(column, context->vcounter, context);\ 2295 read_map_mode4(column, context->vcounter, context);\
2265 CHECK_LIMIT\ 2296 CHECK_LIMIT\
2266 case ((startcyc+1)&0xFF):\ 2297 case ((startcyc+1)&0xFF):\
2298 OUTPUT_PIXEL((startcyc+1)&0xFF)\
2267 if (column & 3) {\ 2299 if (column & 3) {\
2268 scan_sprite_table_mode4(context);\ 2300 scan_sprite_table_mode4(context);\
2269 } else {\ 2301 } else {\
2270 external_slot(context);\ 2302 external_slot(context);\
2271 }\ 2303 }\
2272 CHECK_LIMIT\ 2304 CHECK_LIMIT\
2273 case ((startcyc+2)&0xFF):\ 2305 case ((startcyc+2)&0xFF):\
2306 OUTPUT_PIXEL((startcyc+2)&0xFF)\
2274 fetch_map_mode4(column, context->vcounter, context);\ 2307 fetch_map_mode4(column, context->vcounter, context);\
2275 CHECK_LIMIT\ 2308 CHECK_LIMIT\
2276 case ((startcyc+3)&0xFF):\ 2309 case ((startcyc+3)&0xFF):\
2310 OUTPUT_PIXEL((startcyc+3)&0xFF)\
2277 render_map_mode4(context->vcounter, column, context);\ 2311 render_map_mode4(context->vcounter, column, context);\
2278 CHECK_LIMIT 2312 CHECK_LIMIT
2279 2313
2280 #define CHECK_LIMIT_HSYNC(slot) \ 2314 #define CHECK_LIMIT_HSYNC(slot) \
2281 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \ 2315 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2291 }\ 2325 }\
2292 CHECK_ONLY 2326 CHECK_ONLY
2293 2327
2294 #define SPRITE_RENDER_H40(slot) \ 2328 #define SPRITE_RENDER_H40(slot) \
2295 case slot:\ 2329 case slot:\
2330 OUTPUT_PIXEL_H40(slot)\
2296 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\ 2331 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\
2297 advance_output_line(context);\ 2332 advance_output_line(context);\
2333 if (!context->output) {\
2334 context->output = dummy_buffer;\
2335 }\
2298 }\ 2336 }\
2299 if (slot == 168 || slot == 247 || slot == 248) {\ 2337 if (slot == 168 || slot == 247 || slot == 248) {\
2300 render_border_garbage(\ 2338 render_border_garbage(\
2301 context,\ 2339 context,\
2302 context->sprite_draw_list[context->cur_slot].address,\ 2340 context->sprite_draw_list[context->cur_slot].address,\
2325 2363
2326 //Note that the line advancement check will fail if BG_START_SLOT is > 6 2364 //Note that the line advancement check will fail if BG_START_SLOT is > 6
2327 //as we're bumping up against the hcounter jump 2365 //as we're bumping up against the hcounter jump
2328 #define SPRITE_RENDER_H32(slot) \ 2366 #define SPRITE_RENDER_H32(slot) \
2329 case slot:\ 2367 case slot:\
2368 OUTPUT_PIXEL_H32(slot)\
2330 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\ 2369 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2331 advance_output_line(context);\ 2370 advance_output_line(context);\
2371 if (!context->output) {\
2372 context->output = dummy_buffer;\
2373 }\
2332 }\ 2374 }\
2333 if (slot == 136 || slot == 247 || slot == 248) {\ 2375 if (slot == 136 || slot == 247 || slot == 248) {\
2334 render_border_garbage(\ 2376 render_border_garbage(\
2335 context,\ 2377 context,\
2336 context->sprite_draw_list[context->cur_slot].address,\ 2378 context->sprite_draw_list[context->cur_slot].address,\
2358 2400
2359 #define MODE4_CHECK_SLOT_LINE(slot) \ 2401 #define MODE4_CHECK_SLOT_LINE(slot) \
2360 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \ 2402 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } \
2361 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\ 2403 if ((slot) == BG_START_SLOT + (256+HORIZ_BORDER)/2) {\
2362 advance_output_line(context);\ 2404 advance_output_line(context);\
2405 if (!context->output) {\
2406 context->output = dummy_buffer;\
2407 }\
2363 }\ 2408 }\
2364 if ((slot) == 147) {\ 2409 if ((slot) == 147) {\
2365 context->hslot = 233;\ 2410 context->hslot = 233;\
2366 } else {\ 2411 } else {\
2367 context->hslot++;\ 2412 context->hslot++;\
2377 2422
2378 #define CALC_SLOT(slot, increment) ((slot+increment) > 147 && (slot+increment) < 233 ? (slot+increment-148+233): (slot+increment)) 2423 #define CALC_SLOT(slot, increment) ((slot+increment) > 147 && (slot+increment) < 233 ? (slot+increment-148+233): (slot+increment))
2379 2424
2380 #define SPRITE_RENDER_H32_MODE4(slot) \ 2425 #define SPRITE_RENDER_H32_MODE4(slot) \
2381 case slot:\ 2426 case slot:\
2427 OUTPUT_PIXEL_H32(slot)\
2382 read_sprite_x_mode4(context);\ 2428 read_sprite_x_mode4(context);\
2383 MODE4_CHECK_SLOT_LINE(slot)\ 2429 MODE4_CHECK_SLOT_LINE(slot)\
2384 case CALC_SLOT(slot, 1):\ 2430 case CALC_SLOT(slot, 1):\
2431 OUTPUT_PIXEL(CALC_SLOT(slot, 1))\
2385 read_sprite_x_mode4(context);\ 2432 read_sprite_x_mode4(context);\
2386 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot,1))\ 2433 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot,1))\
2387 case CALC_SLOT(slot, 2):\ 2434 case CALC_SLOT(slot, 2):\
2435 OUTPUT_PIXEL(CALC_SLOT(slot, 2))\
2388 fetch_sprite_cells_mode4(context);\ 2436 fetch_sprite_cells_mode4(context);\
2389 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 2))\ 2437 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 2))\
2390 case CALC_SLOT(slot, 3):\ 2438 case CALC_SLOT(slot, 3):\
2391 if ((slot + 3) == 140) {\ 2439 OUTPUT_PIXEL(CALC_SLOT(slot, 3))\
2392 uint32_t *dst = context->output + BORDER_LEFT + 256 + 8;\
2393 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];\
2394 for (int i = 0; i < BORDER_RIGHT-8; i++, dst++)\
2395 {\
2396 *dst = bgcolor;\
2397 }\
2398 context->done_output = dst;\
2399 }\
2400 render_sprite_cells_mode4(context);\ 2440 render_sprite_cells_mode4(context);\
2401 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 3))\ 2441 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 3))\
2402 case CALC_SLOT(slot, 4):\ 2442 case CALC_SLOT(slot, 4):\
2443 OUTPUT_PIXEL(CALC_SLOT(slot, 4))\
2403 fetch_sprite_cells_mode4(context);\ 2444 fetch_sprite_cells_mode4(context);\
2404 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 4))\ 2445 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 4))\
2405 case CALC_SLOT(slot, 5):\ 2446 case CALC_SLOT(slot, 5):\
2447 OUTPUT_PIXEL(CALC_SLOT(slot, 5))\
2406 render_sprite_cells_mode4(context);\ 2448 render_sprite_cells_mode4(context);\
2407 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5)) 2449 MODE4_CHECK_SLOT_LINE(CALC_SLOT(slot, 5))
2408 2450
2451 static uint32_t dummy_buffer[LINEBUF_SIZE];
2409 static void vdp_h40(vdp_context * context, uint32_t target_cycles) 2452 static void vdp_h40(vdp_context * context, uint32_t target_cycles)
2410 { 2453 {
2411 uint16_t address; 2454 uint16_t address;
2412 uint32_t mask; 2455 uint32_t mask;
2413 uint32_t const slot_cycles = MCLKS_SLOT_H40; 2456 uint32_t const slot_cycles = MCLKS_SLOT_H40;
2457 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
2458 uint8_t test_layer = context->test_port >> 7 & 3;
2459 if (!context->output) {
2460 //This shouldn't happen normally, but it can theoretically
2461 //happen when doing border busting
2462 context->output = dummy_buffer;
2463 }
2414 switch(context->hslot) 2464 switch(context->hslot)
2415 { 2465 {
2416 for (;;) 2466 for (;;)
2417 { 2467 {
2418 case 165: 2468 case 165:
2469 OUTPUT_PIXEL(165)
2419 if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) { 2470 if (!(context->regs[REG_MODE_3] & BIT_VSCROLL)) {
2420 //TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode 2471 //TODO: Develop some tests on hardware to see when vscroll latch actually happens for full plane mode
2421 //See note in vdp_h32 for why this was originally moved out of read_map_scroll 2472 //See note in vdp_h32 for why this was originally moved out of read_map_scroll
2422 //Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232 2473 //Skitchin' has a similar problem, but uses H40 mode. It seems to be able to hit the extern slot at 232
2423 //pretty consistently 2474 //pretty consistently
2424 context->vscroll_latch[0] = context->vsram[0]; 2475 context->vscroll_latch[0] = context->vsram[0];
2425 context->vscroll_latch[1] = context->vsram[1]; 2476 context->vscroll_latch[1] = context->vsram[1];
2426 } 2477 }
2427 if (context->state == PREPARING) { 2478 if (context->state == PREPARING) {
2428 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2429 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2430 if (dst >= context->done_output) {
2431 *dst = bg_color;
2432 }
2433 dst++;
2434 if (dst >= context->done_output) {
2435 *dst = bg_color;
2436 }
2437 external_slot(context); 2479 external_slot(context);
2438 } else { 2480 } else {
2439 render_sprite_cells(context); 2481 render_sprite_cells(context);
2440 } 2482 }
2441 CHECK_LIMIT 2483 CHECK_LIMIT
2442 case 166: 2484 case 166:
2485 OUTPUT_PIXEL(166)
2443 if (context->state == PREPARING) { 2486 if (context->state == PREPARING) {
2444 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2445 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2446 if (dst >= context->done_output) {
2447 *dst = bg_color;
2448 }
2449 dst++;
2450 if (dst >= context->done_output) {
2451 *dst = bg_color;
2452 }
2453 external_slot(context); 2487 external_slot(context);
2454 } else { 2488 } else {
2455 render_sprite_cells(context); 2489 render_sprite_cells(context);
2456 } 2490 }
2457 if (context->vcounter == context->inactive_start) { 2491 if (context->vcounter == context->inactive_start) {
2460 return; 2494 return;
2461 } 2495 }
2462 CHECK_LIMIT 2496 CHECK_LIMIT
2463 //sprite attribute table scan starts 2497 //sprite attribute table scan starts
2464 case 167: 2498 case 167:
2465 if (context->state == PREPARING) { 2499 OUTPUT_PIXEL(167)
2466 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2467 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2468 for (int i = 0; i < LINEBUF_SIZE - 2 * (context->hslot - BG_START_SLOT); i++, dst++)
2469 {
2470 if (dst >= context->done_output) {
2471 *dst = bg_color;
2472 }
2473 }
2474 }
2475 context->sprite_index = 0x80; 2500 context->sprite_index = 0x80;
2476 context->slot_counter = 0; 2501 context->slot_counter = 0;
2477 render_border_garbage( 2502 render_border_garbage(
2478 context, 2503 context,
2479 context->sprite_draw_list[context->cur_slot].address, 2504 context->sprite_draw_list[context->cur_slot].address,
2589 COLUMN_RENDER_BLOCK(34, 129) 2614 COLUMN_RENDER_BLOCK(34, 129)
2590 COLUMN_RENDER_BLOCK(36, 137) 2615 COLUMN_RENDER_BLOCK(36, 137)
2591 COLUMN_RENDER_BLOCK(38, 145) 2616 COLUMN_RENDER_BLOCK(38, 145)
2592 COLUMN_RENDER_BLOCK_REFRESH(40, 153) 2617 COLUMN_RENDER_BLOCK_REFRESH(40, 153)
2593 case 161: 2618 case 161:
2619 OUTPUT_PIXEL(161)
2594 external_slot(context); 2620 external_slot(context);
2595 CHECK_LIMIT 2621 CHECK_LIMIT
2596 case 162: 2622 case 162:
2623 OUTPUT_PIXEL(162)
2597 external_slot(context); 2624 external_slot(context);
2598 CHECK_LIMIT 2625 CHECK_LIMIT
2599 //sprite render to line buffer starts 2626 //sprite render to line buffer starts
2600 case 163: 2627 case 163:
2628 OUTPUT_PIXEL(163)
2601 context->cur_slot = MAX_DRAWS-1; 2629 context->cur_slot = MAX_DRAWS-1;
2602 memset(context->linebuf, 0, LINEBUF_SIZE); 2630 memset(context->linebuf, 0, LINEBUF_SIZE);
2603 render_border_garbage( 2631 render_border_garbage(
2604 context, 2632 context,
2605 context->sprite_draw_list[context->cur_slot].address, 2633 context->sprite_draw_list[context->cur_slot].address,
2607 context->col_1 2635 context->col_1
2608 ); 2636 );
2609 render_sprite_cells(context); 2637 render_sprite_cells(context);
2610 CHECK_LIMIT 2638 CHECK_LIMIT
2611 case 164: 2639 case 164:
2640 OUTPUT_PIXEL(164)
2612 render_border_garbage( 2641 render_border_garbage(
2613 context, 2642 context,
2614 context->sprite_draw_list[context->cur_slot].address, 2643 context->sprite_draw_list[context->cur_slot].address,
2615 context->tmp_buf_a, context->buf_a_off + 8, 2644 context->tmp_buf_a, context->buf_a_off + 8,
2616 context->col_2 2645 context->col_2
2634 static void vdp_h32(vdp_context * context, uint32_t target_cycles) 2663 static void vdp_h32(vdp_context * context, uint32_t target_cycles)
2635 { 2664 {
2636 uint16_t address; 2665 uint16_t address;
2637 uint32_t mask; 2666 uint32_t mask;
2638 uint32_t const slot_cycles = MCLKS_SLOT_H32; 2667 uint32_t const slot_cycles = MCLKS_SLOT_H32;
2668 uint8_t bgindex = context->regs[REG_BG_COLOR] & 0x3F;
2669 uint8_t test_layer = context->test_port >> 7 & 3;
2670 if (!context->output) {
2671 //This shouldn't happen normally, but it can theoretically
2672 //happen when doing border busting
2673 context->output = dummy_buffer;
2674 }
2639 switch(context->hslot) 2675 switch(context->hslot)
2640 { 2676 {
2641 for (;;) 2677 for (;;)
2642 { 2678 {
2643 case 133: 2679 case 133:
2680 OUTPUT_PIXEL(133)
2644 if (context->state == PREPARING) { 2681 if (context->state == PREPARING) {
2645 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2646 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2647 if (dst >= context->done_output) {
2648 *dst = bg_color;
2649 }
2650 dst++;
2651 if (dst >= context->done_output) {
2652 *dst = bg_color;
2653 }
2654 external_slot(context); 2682 external_slot(context);
2655 } else { 2683 } else {
2656 render_sprite_cells(context); 2684 render_sprite_cells(context);
2657 } 2685 }
2658 CHECK_LIMIT 2686 CHECK_LIMIT
2659 case 134: 2687 case 134:
2688 OUTPUT_PIXEL(134)
2660 if (context->state == PREPARING) { 2689 if (context->state == PREPARING) {
2661 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2662 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2663 if (dst >= context->done_output) {
2664 *dst = bg_color;
2665 }
2666 dst++;
2667 if (dst >= context->done_output) {
2668 *dst = bg_color;
2669 }
2670 external_slot(context); 2690 external_slot(context);
2671 } else { 2691 } else {
2672 render_sprite_cells(context); 2692 render_sprite_cells(context);
2673 } 2693 }
2674 if (context->vcounter == context->inactive_start) { 2694 if (context->vcounter == context->inactive_start) {
2677 return; 2697 return;
2678 } 2698 }
2679 CHECK_LIMIT 2699 CHECK_LIMIT
2680 //sprite attribute table scan starts 2700 //sprite attribute table scan starts
2681 case 135: 2701 case 135:
2682 if (context->state == PREPARING) { 2702 OUTPUT_PIXEL(135)
2683 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
2684 uint32_t *dst = context->output + (context->hslot - BG_START_SLOT) * 2;
2685 for (int i = 0; i < (256+HORIZ_BORDER) - 2 * (context->hslot - BG_START_SLOT); i++)
2686 {
2687 if (dst >= context->done_output) {
2688 *(dst++) = bg_color;
2689 }
2690 }
2691 }
2692 context->sprite_index = 0x80; 2703 context->sprite_index = 0x80;
2693 context->slot_counter = 0; 2704 context->slot_counter = 0;
2694 render_border_garbage( 2705 render_border_garbage(
2695 context, 2706 context,
2696 context->sprite_draw_list[context->cur_slot].address, 2707 context->sprite_draw_list[context->cur_slot].address,
2708 SPRITE_RENDER_H32(141) 2719 SPRITE_RENDER_H32(141)
2709 SPRITE_RENDER_H32(142) 2720 SPRITE_RENDER_H32(142)
2710 SPRITE_RENDER_H32(143) 2721 SPRITE_RENDER_H32(143)
2711 SPRITE_RENDER_H32(144) 2722 SPRITE_RENDER_H32(144)
2712 case 145: 2723 case 145:
2724 OUTPUT_PIXEL(145)
2713 external_slot(context); 2725 external_slot(context);
2714 CHECK_LIMIT 2726 CHECK_LIMIT
2715 SPRITE_RENDER_H32(146) 2727 SPRITE_RENDER_H32(146)
2716 SPRITE_RENDER_H32(147) 2728 SPRITE_RENDER_H32(147)
2717 SPRITE_RENDER_H32(233) 2729 SPRITE_RENDER_H32(233)
2813 COLUMN_RENDER_BLOCK(26, 97) 2825 COLUMN_RENDER_BLOCK(26, 97)
2814 COLUMN_RENDER_BLOCK(28, 105) 2826 COLUMN_RENDER_BLOCK(28, 105)
2815 COLUMN_RENDER_BLOCK(30, 113) 2827 COLUMN_RENDER_BLOCK(30, 113)
2816 COLUMN_RENDER_BLOCK_REFRESH(32, 121) 2828 COLUMN_RENDER_BLOCK_REFRESH(32, 121)
2817 case 129: 2829 case 129:
2830 OUTPUT_PIXEL(129)
2818 external_slot(context); 2831 external_slot(context);
2819 CHECK_LIMIT 2832 CHECK_LIMIT
2820 case 130: { 2833 case 130: {
2834 OUTPUT_PIXEL(130)
2821 external_slot(context); 2835 external_slot(context);
2822 CHECK_LIMIT 2836 CHECK_LIMIT
2823 } 2837 }
2824 //sprite render to line buffer starts 2838 //sprite render to line buffer starts
2825 case 131: 2839 case 131:
2840 OUTPUT_PIXEL(131)
2826 context->cur_slot = MAX_DRAWS_H32-1; 2841 context->cur_slot = MAX_DRAWS_H32-1;
2827 memset(context->linebuf, 0, LINEBUF_SIZE); 2842 memset(context->linebuf, 0, LINEBUF_SIZE);
2828 render_border_garbage( 2843 render_border_garbage(
2829 context, 2844 context,
2830 context->sprite_draw_list[context->cur_slot].address, 2845 context->sprite_draw_list[context->cur_slot].address,
2832 context->col_1 2847 context->col_1
2833 ); 2848 );
2834 render_sprite_cells(context); 2849 render_sprite_cells(context);
2835 CHECK_LIMIT 2850 CHECK_LIMIT
2836 case 132: 2851 case 132:
2852 OUTPUT_PIXEL(132)
2837 render_border_garbage( 2853 render_border_garbage(
2838 context, 2854 context,
2839 context->sprite_draw_list[context->cur_slot].address, 2855 context->sprite_draw_list[context->cur_slot].address,
2840 context->tmp_buf_a, context->buf_a_off + 8, 2856 context->tmp_buf_a, context->buf_a_off + 8,
2841 context->col_2 2857 context->col_2
2858 static void vdp_h32_mode4(vdp_context * context, uint32_t target_cycles) 2874 static void vdp_h32_mode4(vdp_context * context, uint32_t target_cycles)
2859 { 2875 {
2860 uint16_t address; 2876 uint16_t address;
2861 uint32_t mask; 2877 uint32_t mask;
2862 uint32_t const slot_cycles = MCLKS_SLOT_H32; 2878 uint32_t const slot_cycles = MCLKS_SLOT_H32;
2879 uint8_t bgindex = 0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET;
2880 uint8_t test_layer = context->test_port >> 7 & 3;
2881 if (!context->output) {
2882 //This shouldn't happen normally, but it can theoretically
2883 //happen when doing border busting
2884 context->output = dummy_buffer;
2885 }
2863 switch(context->hslot) 2886 switch(context->hslot)
2864 { 2887 {
2865 for (;;) 2888 for (;;)
2866 { 2889 {
2867 //sprite rendering starts 2890 //sprite rendering starts
2907 case 255: 2930 case 255:
2908 scan_sprite_table_mode4(context); 2931 scan_sprite_table_mode4(context);
2909 CHECK_LIMIT 2932 CHECK_LIMIT
2910 case 0: { 2933 case 0: {
2911 scan_sprite_table_mode4(context); 2934 scan_sprite_table_mode4(context);
2912 uint32_t *dst = context->output;;
2913 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2914 for (int i = 0; i < BORDER_LEFT-8; i++, dst++)
2915 {
2916 *dst = bgcolor;
2917 }
2918 context->done_output = dst;
2919 CHECK_LIMIT 2935 CHECK_LIMIT
2920 } 2936 }
2921 case 1: 2937 case 1:
2922 scan_sprite_table_mode4(context); 2938 scan_sprite_table_mode4(context);
2923 CHECK_LIMIT 2939 CHECK_LIMIT
2929 CHECK_LIMIT 2945 CHECK_LIMIT
2930 case 4: { 2946 case 4: {
2931 scan_sprite_table_mode4(context); 2947 scan_sprite_table_mode4(context);
2932 context->buf_a_off = 8; 2948 context->buf_a_off = 8;
2933 memset(context->tmp_buf_a, 0, 8); 2949 memset(context->tmp_buf_a, 0, 8);
2934 uint32_t *dst = context->output + BORDER_LEFT - 8;
2935 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2936 for (int i = 0; i < 8; i++, dst++)
2937 {
2938 *dst = bgcolor;
2939 }
2940 context->done_output = dst;
2941 CHECK_LIMIT 2950 CHECK_LIMIT
2942 } 2951 }
2943 COLUMN_RENDER_BLOCK_MODE4(0, 5) 2952 COLUMN_RENDER_BLOCK_MODE4(0, 5)
2944 COLUMN_RENDER_BLOCK_MODE4(1, 9) 2953 COLUMN_RENDER_BLOCK_MODE4(1, 9)
2945 COLUMN_RENDER_BLOCK_MODE4(2, 13) 2954 COLUMN_RENDER_BLOCK_MODE4(2, 13)
2971 COLUMN_RENDER_BLOCK_MODE4(28, 117) 2980 COLUMN_RENDER_BLOCK_MODE4(28, 117)
2972 COLUMN_RENDER_BLOCK_MODE4(29, 121) 2981 COLUMN_RENDER_BLOCK_MODE4(29, 121)
2973 COLUMN_RENDER_BLOCK_MODE4(30, 125) 2982 COLUMN_RENDER_BLOCK_MODE4(30, 125)
2974 COLUMN_RENDER_BLOCK_MODE4(31, 129) 2983 COLUMN_RENDER_BLOCK_MODE4(31, 129)
2975 case 133: 2984 case 133:
2985 OUTPUT_PIXEL(133)
2976 external_slot(context); 2986 external_slot(context);
2977 CHECK_LIMIT 2987 CHECK_LIMIT
2978 case 134: 2988 case 134:
2989 OUTPUT_PIXEL(134)
2979 external_slot(context); 2990 external_slot(context);
2980 CHECK_LIMIT 2991 CHECK_LIMIT
2981 case 135: 2992 case 135:
2993 OUTPUT_PIXEL(135)
2982 external_slot(context); 2994 external_slot(context);
2983 CHECK_LIMIT 2995 CHECK_LIMIT
2984 case 136: { 2996 case 136: {
2997 OUTPUT_PIXEL(136)
2985 external_slot(context); 2998 external_slot(context);
2986 //set things up for sprite rendering in the next slot 2999 //set things up for sprite rendering in the next slot
2987 memset(context->linebuf, 0, LINEBUF_SIZE); 3000 memset(context->linebuf, 0, LINEBUF_SIZE);
2988 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1; 3001 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1;
2989 context->sprite_draws = MAX_DRAWS_H32_MODE4; 3002 context->sprite_draws = MAX_DRAWS_H32_MODE4;
2990 uint32_t *dst = context->output + BORDER_LEFT + 256;
2991 uint32_t bgcolor = context->colors[0x10 | (context->regs[REG_BG_COLOR] & 0xF) + MODE4_OFFSET];
2992 for (int i = 0; i < 8; i++, dst++)
2993 {
2994 *dst = bgcolor;
2995 }
2996 context->done_output = dst;
2997 CHECK_LIMIT 3003 CHECK_LIMIT
2998 }} 3004 }}
2999 default: 3005 default:
3000 context->hslot++; 3006 context->hslot++;
3001 context->cycles += MCLKS_SLOT_H32; 3007 context->cycles += MCLKS_SLOT_H32;
3006 { 3012 {
3007 uint8_t max_slot = is_h40 ? 169 : 136; 3013 uint8_t max_slot = is_h40 ? 169 : 136;
3008 if (context->hslot > max_slot) { 3014 if (context->hslot > max_slot) {
3009 return; 3015 return;
3010 } 3016 }
3011 uint32_t *dst = context->output + (context->hslot >> 3) * SCROLL_BUFFER_DRAW; 3017 uint8_t *dst = context->compositebuf + (context->hslot >> 3) * SCROLL_BUFFER_DRAW;
3012 int32_t len; 3018 int32_t len;
3013 uint32_t src_off; 3019 uint32_t src_off;
3014 if (context->hslot) { 3020 if (context->hslot) {
3015 dst -= SCROLL_BUFFER_DRAW - BORDER_LEFT; 3021 dst -= SCROLL_BUFFER_DRAW - BORDER_LEFT;
3016 src_off = 0; 3022 src_off = 0;
3017 len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW; 3023 len = context->hslot == max_slot ? BORDER_RIGHT : SCROLL_BUFFER_DRAW;
3018 } else { 3024 } else {
3019 src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT; 3025 src_off = SCROLL_BUFFER_DRAW - BORDER_LEFT;
3020 len = BORDER_LEFT; 3026 len = BORDER_LEFT;
3021 } 3027 }
3022 uint8_t *src; 3028 uint8_t *src = NULL;
3023 if (test_layer == 2) { 3029 if (test_layer == 2) {
3024 //plane A 3030 //plane A
3025 src_off += context->buf_a_off + context->hscroll_a; 3031 src_off += context->buf_a_off + context->hscroll_a;
3026 src = context->tmp_buf_a; 3032 src = context->tmp_buf_a;
3027 } else if (test_layer == 3){ 3033 } else if (test_layer == 3){
3028 //plane B 3034 //plane B
3029 src_off += context->buf_b_off + context->hscroll_b; 3035 src_off += context->buf_b_off + context->hscroll_b;
3030 src = context->tmp_buf_b; 3036 src = context->tmp_buf_b;
3031 } else { 3037 } else {
3032 //sprite layer 3038 //sprite layer
3039 memset(dst, 0, len);
3040 dst += len;
3041 len = 0;
3042 }
3043 if (src) {
3033 for (; len >=0; len--, dst++, src_off++) 3044 for (; len >=0; len--, dst++, src_off++)
3034 { 3045 {
3035 *dst = context->colors[0]; 3046 *dst = src[src_off & SCROLL_BUFFER_MASK] & 0x3F;
3036 } 3047 }
3037 } 3048 }
3038 for (; len >=0; len--, dst++, src_off++) 3049 context->done_composite = dst;
3039 {
3040 *dst = context->colors[src[src_off & SCROLL_BUFFER_MASK] & 0x3F];
3041 }
3042 context->done_output = dst;
3043 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW; 3050 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3044 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW; 3051 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_DRAW;
3045 } 3052 }
3046 3053
3047 static void check_switch_inactive(vdp_context *context, uint8_t is_h40) 3054 static void check_switch_inactive(vdp_context *context, uint8_t is_h40)
3111 active_line = 0x200; 3118 active_line = 0x200;
3112 } 3119 }
3113 } 3120 }
3114 uint32_t *dst; 3121 uint32_t *dst;
3115 uint8_t *debug_dst; 3122 uint8_t *debug_dst;
3116 if ( 3123 if (context->output && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot) {
3117 (
3118 context->vcounter < context->inactive_start + context->border_bot
3119 || context->vcounter >= 0x200 - context->border_top
3120 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot
3121 ) {
3122 dst = context->output + 2 * (context->hslot - BG_START_SLOT); 3124 dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3123 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); 3125 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3124 } else { 3126 } else {
3125 dst = NULL; 3127 dst = NULL;
3126 } 3128 }
3127 3129
3128 if (
3129 !dst && context->vcounter == context->inactive_start + context->border_bot
3130 && context->hslot >= line_change && context->hslot < bg_end_slot
3131 ) {
3132 dst = context->output + 2 * (context->hslot - BG_START_SLOT);
3133 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3134 }
3135
3136 uint8_t test_layer = context->test_port >> 7 & 3; 3130 uint8_t test_layer = context->test_port >> 7 & 3;
3137 if (test_layer) {
3138 dst = NULL;
3139 }
3140 3131
3141 while(context->cycles < target_cycles) 3132 while(context->cycles < target_cycles)
3142 { 3133 {
3143 check_switch_inactive(context, is_h40); 3134 check_switch_inactive(context, is_h40);
3144 if (context->hslot == BG_START_SLOT && !test_layer && ( 3135 if (context->hslot == BG_START_SLOT && context->output) {
3145 context->vcounter < context->inactive_start + context->border_bot
3146 || context->vcounter >= 0x200 - context->border_top
3147 )) {
3148 dst = context->output + (context->hslot - BG_START_SLOT) * 2; 3136 dst = context->output + (context->hslot - BG_START_SLOT) * 2;
3149 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT); 3137 debug_dst = context->layer_debug_buf + 2 * (context->hslot - BG_START_SLOT);
3150 } else if (context->hslot == bg_end_slot) { 3138 } else if (context->hslot == bg_end_slot) {
3151 advance_output_line(context); 3139 advance_output_line(context);
3152 dst = NULL; 3140 dst = NULL;
3198 } else if (context->vcounter == context->inactive_start && context->hslot == 1 && (context->regs[REG_MODE_4] & BIT_INTERLACE)) { 3186 } else if (context->vcounter == context->inactive_start && context->hslot == 1 && (context->regs[REG_MODE_4] & BIT_INTERLACE)) {
3199 context->flags2 ^= FLAG2_EVEN_FIELD; 3187 context->flags2 ^= FLAG2_EVEN_FIELD;
3200 } 3188 }
3201 3189
3202 if (dst) { 3190 if (dst) {
3191 uint8_t bg_index;
3203 if (mode_5) { 3192 if (mode_5) {
3204 bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 3193 bg_index = context->regs[REG_BG_COLOR] & 0x3F;
3194 bg_color = context->colors[bg_index];
3205 } else if (context->regs[REG_MODE_1] & BIT_MODE_4) { 3195 } else if (context->regs[REG_MODE_1] & BIT_MODE_4) {
3206 bg_color = context->colors[MODE4_OFFSET + 0x10 + (context->regs[REG_BG_COLOR] & 0xF)]; 3196 bg_index = 0x10 + (context->regs[REG_BG_COLOR] & 0xF);
3207 } 3197 bg_color = context->colors[MODE4_OFFSET + bg_index];
3208 if (dst >= context->done_output) { 3198 }
3199 if (context->done_composite) {
3200 uint8_t pixel = context->compositebuf[dst-context->output];
3201 if (!(pixel & 0x3F | test_layer)) {
3202 pixel = pixel & 0xC0 | bg_index;
3203 }
3204 *(dst++) = context->colors[pixel];
3205 if ((dst - context->output) == (context->done_composite - context->compositebuf)) {
3206 context->done_composite = NULL;
3207 memset(context->compositebuf, 0, sizeof(context->compositebuf));
3208 }
3209 } else {
3209 *(dst++) = bg_color; 3210 *(dst++) = bg_color;
3210 *(debug_dst++) = DBG_SRC_BG; 3211 *(debug_dst++) = DBG_SRC_BG;
3212 }
3213 if (context->done_composite) {
3214 uint8_t pixel = context->compositebuf[dst-context->output];
3215 if (!(pixel & 0x3F | test_layer)) {
3216 pixel = pixel & 0xC0 | bg_index;
3217 }
3218 *(dst++) = context->colors[pixel];
3219 if ((dst - context->output) == (context->done_composite - context->compositebuf)) {
3220 context->done_composite = NULL;
3221 memset(context->compositebuf, 0, sizeof(context->compositebuf));
3222 }
3211 } else { 3223 } else {
3212 dst++;
3213 debug_dst++;
3214 }
3215 if (dst >= context->done_output) {
3216 *(dst++) = bg_color; 3224 *(dst++) = bg_color;
3217 *(debug_dst++) = DBG_SRC_BG; 3225 *(debug_dst++) = DBG_SRC_BG;
3218 context->done_output = dst; 3226 }
3219 } else { 3227
3220 dst++;
3221 debug_dst++;
3222 }
3223 if (context->hslot == (bg_end_slot-1)) { 3228 if (context->hslot == (bg_end_slot-1)) {
3224 *(dst++) = bg_color; 3229 if (context->done_composite) {
3225 *(debug_dst++) = DBG_SRC_BG; 3230 uint8_t pixel = context->compositebuf[dst-context->output];
3226 context->done_output = dst; 3231 if (!(pixel & 0x3F | test_layer)) {
3232 pixel = pixel & 0xC0 | bg_index;
3233 }
3234 *(dst++) = context->colors[pixel];
3235 if ((dst - context->output) == (context->done_composite - context->compositebuf)) {
3236 context->done_composite = NULL;
3237 memset(context->compositebuf, 0, sizeof(context->compositebuf));
3238 }
3239 } else {
3240 *(dst++) = bg_color;
3241 *(debug_dst++) = DBG_SRC_BG;
3242 }
3227 } 3243 }
3228 } 3244 }
3229 3245
3230 if (!is_refresh(context, context->hslot)) { 3246 if (!is_refresh(context, context->hslot)) {
3231 external_slot(context); 3247 external_slot(context);