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