comparison vdp.c @ 1821:4f3443ecb6d6

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