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