Mercurial > repos > blastem
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); |