comparison vdp.c @ 1337:d092c15246a3

Initial stab at horizontal border when VDP test register layer selection is in effect for H40. Extended horizontal borders in Titancade scene and ninja escape scene mostly correct now
author Michael Pavone <pavone@retrodev.com>
date Sat, 29 Apr 2017 16:51:57 -0700
parents 26e72126f9d1
children 3706b683cd48
comparison
equal deleted inserted replaced
1336:baaf05fd64c4 1337:d092c15246a3
314 context->flags2 |= FLAG2_SPRITE_COLLIDE; 314 context->flags2 |= FLAG2_SPRITE_COLLIDE;
315 } 315 }
316 } 316 }
317 x += dir; 317 x += dir;
318 } 318 }
319 } else {
320 context->cur_slot--;
319 } 321 }
320 } 322 }
321 323
322 static void fetch_sprite_cells_mode4(vdp_context * context) 324 static void fetch_sprite_cells_mode4(vdp_context * context)
323 { 325 {
715 int16_t i; 717 int16_t i;
716 if (context->flags & FLAG_MASKED) { 718 if (context->flags & FLAG_MASKED) {
717 for (i=0; i < width && context->sprite_draws; i++) { 719 for (i=0; i < width && context->sprite_draws; i++) {
718 --context->sprite_draws; 720 --context->sprite_draws;
719 context->sprite_draw_list[context->sprite_draws].x_pos = -128; 721 context->sprite_draw_list[context->sprite_draws].x_pos = -128;
722 context->sprite_draw_list[context->sprite_draws].address = address + i * height * 4;
720 } 723 }
721 } else { 724 } else {
722 x -= 128; 725 x -= 128;
723 int16_t base_x = x; 726 int16_t base_x = x;
724 int16_t dir; 727 int16_t dir;
1263 } 1266 }
1264 1267
1265 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) 1268 static void render_map_output(uint32_t line, int32_t col, vdp_context * context)
1266 { 1269 {
1267 uint32_t *dst; 1270 uint32_t *dst;
1271 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
1272 uint8_t test_layer = context->test_port >> 7 & 3;
1268 if (context->state == PREPARING) { 1273 if (context->state == PREPARING) {
1269 if (!col) {
1270 return;
1271 }
1272 col -= 2;
1273 if (col) { 1274 if (col) {
1275 col -= 2;
1274 dst = context->output + BORDER_LEFT + col * 8; 1276 dst = context->output + BORDER_LEFT + col * 8;
1275 } else { 1277 } else {
1276 dst = context->output; 1278 dst = context->output;
1277 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 1279 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1278 for (int i = 0; i < BORDER_LEFT; i++, dst++) 1280 for (int i = 0; i < BORDER_LEFT; i++, dst++)
1279 { 1281 {
1280 *dst = bg_color; 1282 *dst = bg_color;
1281 } 1283 }
1284 return;
1282 } 1285 }
1283 uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; 1286 uint32_t color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1284 for (int i = 0; i < 16; i++) 1287 for (int i = 0; i < 16; i++)
1285 { 1288 {
1286 *(dst++) = color; 1289 *(dst++) = color;
1292 uint8_t *sprite_buf, *plane_a, *plane_b; 1295 uint8_t *sprite_buf, *plane_a, *plane_b;
1293 int plane_a_off, plane_b_off; 1296 int plane_a_off, plane_b_off;
1294 if (col) 1297 if (col)
1295 { 1298 {
1296 col-=2; 1299 col-=2;
1297 if (col) { 1300 dst = context->output + BORDER_LEFT + col * 8;
1298 dst = context->output + BORDER_LEFT + col * 8;
1299 } else {
1300 dst = context->output;
1301 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F];
1302 for (int i = 0; i < BORDER_LEFT; i++, dst++)
1303 {
1304 *dst = bg_color;
1305 }
1306 }
1307 if (context->debug < 2) { 1301 if (context->debug < 2) {
1308 sprite_buf = context->linebuf + col * 8; 1302 sprite_buf = context->linebuf + col * 8;
1309 uint8_t a_src, src; 1303 uint8_t a_src, src;
1310 if (context->flags & FLAG_WINDOW) { 1304 if (context->flags & FLAG_WINDOW) {
1311 plane_a_off = context->buf_a_off; 1305 plane_a_off = context->buf_a_off;
1314 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF); 1308 plane_a_off = context->buf_a_off - (context->hscroll_a & 0xF);
1315 a_src = DBG_SRC_A; 1309 a_src = DBG_SRC_A;
1316 } 1310 }
1317 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF); 1311 plane_b_off = context->buf_b_off - (context->hscroll_b & 0xF);
1318 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7)); 1312 //printf("A | tmp_buf offset: %d\n", 8 - (context->hscroll_a & 0x7));
1319 uint8_t output_disabled = (context->test_port & TEST_BIT_DISABLE) != 0;
1320 uint8_t test_layer = context->test_port >> 7 & 3;
1321 1313
1322 if (context->regs[REG_MODE_4] & BIT_HILIGHT) { 1314 if (context->regs[REG_MODE_4] & BIT_HILIGHT) {
1323 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) { 1315 for (int i = 0; i < 16; ++plane_a_off, ++plane_b_off, ++sprite_buf, ++i) {
1324 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK); 1316 plane_a = context->tmp_buf_a + (plane_a_off & SCROLL_BUFFER_MASK);
1325 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK); 1317 plane_b = context->tmp_buf_b + (plane_b_off & SCROLL_BUFFER_MASK);
1488 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)]; 1480 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] >> 4)];
1489 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)]; 1481 *(dst++) = context->colors[(context->debug_pal << 4) | (context->vdpmem[address] & 0xF)];
1490 address++; 1482 address++;
1491 } 1483 }
1492 } 1484 }
1485 } else {
1486 dst = context->output;
1487 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1488 if (output_disabled) {
1489 pixel = 0x3F;
1490 }
1491 uint32_t bg_color = context->colors[pixel];
1492 if (test_layer) {
1493 switch(test_layer)
1494 {
1495 case 1:
1496 //TODO: Display garbage from bus?
1497 for (int i = 0; i < BORDER_LEFT; i++, dst++)
1498 {
1499 *dst = bg_color;
1500 }
1501 break;
1502 case 2: {
1503 //plane A
1504 //TODO: Deal with Window layer
1505 int i;
1506 /*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++)
1507 {
1508 *dst = bg_color;
1509 }*/
1510 i = 0;
1511 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF) + (16 - BORDER_LEFT);
1512 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
1513 for (; i < BORDER_LEFT; buf_off++, i++, dst++)
1514 {
1515 *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK]];
1516 }
1517 break;
1518 }
1519 case 3: {
1520 //plane B
1521 int i;
1522 /*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++)
1523 {
1524 *dst = bg_color;
1525 }*/
1526 i = 0;
1527 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF) + (16 - BORDER_LEFT);
1528 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
1529 for (; i < BORDER_LEFT; buf_off++, i++, dst++)
1530 {
1531 *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK]];
1532 }
1533 break;
1534 }
1535 }
1536 } else {
1537 for (int i = 0; i < BORDER_LEFT; i++, dst++)
1538 {
1539 *dst = bg_color;
1540 }
1541 }
1493 } 1542 }
1494 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 1543 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1495 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK; 1544 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1496 } 1545 }
1497 1546
1693 #endif 1742 #endif
1694 if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) { 1743 if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) {
1695 context->h40_lines++; 1744 context->h40_lines++;
1696 } 1745 }
1697 } 1746 }
1747 }
1748
1749 static void render_border_garbage(vdp_context *context, uint32_t address, uint8_t *buf, uint8_t buf_off, uint16_t col)
1750 {
1751 uint8_t base = col >> 9 & 0x30;
1752 for (int i = 0; i < 4; i++, address++)
1753 {
1754 uint8_t byte = context->vdpmem[address & 0xFFFF];
1755 buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte >> 4;
1756 buf[(buf_off++) & SCROLL_BUFFER_MASK] = base | byte & 0xF;
1757 }
1758 }
1759
1760 static void draw_right_border(vdp_context *context)
1761 {
1762 uint32_t *dst = context->output + BORDER_LEFT + ((context->regs[REG_MODE_4] & BIT_H40) ? 320 : 256);
1763 uint8_t pixel = context->regs[REG_BG_COLOR] & 0x3F;
1764 if ((context->test_port & TEST_BIT_DISABLE) != 0) {
1765 pixel = 0x3F;
1766 }
1767 uint32_t bg_color = context->colors[pixel];
1768 uint8_t test_layer = context->test_port >> 7 & 3;
1769 if (test_layer) {
1770 switch(test_layer)
1771 {
1772 case 1:
1773 //TODO: Display garbage from bus?
1774 for (int i = 0; i < BORDER_RIGHT; i++, dst++)
1775 {
1776 *dst = bg_color;
1777 }
1778 break;
1779 case 2: {
1780 //plane A
1781 //TODO: Deal with Window layer
1782 int i;
1783 /*for (i = 0; i < (context->hscroll_a & 0xF) - (16 - BORDER_LEFT); i++, dst++)
1784 {
1785 *dst = bg_color;
1786 }*/
1787 i = 0;
1788 uint8_t buf_off = context->buf_a_off - (context->hscroll_a & 0xF);
1789 //uint8_t *src = context->tmp_buf_a + ((context->buf_a_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_a & 0xF))) & SCROLL_BUFFER_MASK);
1790 for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
1791 {
1792 *dst = context->colors[context->tmp_buf_a[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
1793 }
1794 break;
1795 }
1796 case 3: {
1797 //plane B
1798 int i;
1799 /*for (i = 0; i < (context->hscroll_b & 0xF) - (16 - BORDER_LEFT); i++, dst++)
1800 {
1801 *dst = bg_color;
1802 }*/
1803 i = 0;
1804 uint8_t buf_off = context->buf_b_off - (context->hscroll_b & 0xF);
1805 //uint8_t *src = context->tmp_buf_b + ((context->buf_b_off + (i ? 0 : (16 - BORDER_LEFT) - (context->hscroll_b & 0xF))) & SCROLL_BUFFER_MASK);
1806 for (; i < BORDER_RIGHT; buf_off++, i++, dst++)
1807 {
1808 *dst = context->colors[context->tmp_buf_b[buf_off & SCROLL_BUFFER_MASK] & 0x3F];
1809 }
1810 break;
1811 }
1812 }
1813 } else {
1814 for (int i = 0; i < BORDER_RIGHT; i++, dst++)
1815 {
1816 *dst = bg_color;
1817 }
1818 }
1819 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1820 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;
1698 } 1821 }
1699 1822
1700 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; } 1823 #define CHECK_ONLY if (context->cycles >= target_cycles) { return; }
1701 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY 1824 #define CHECK_LIMIT if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } context->hslot++; context->cycles += slot_cycles; CHECK_ONLY
1702 1825
1788 1911
1789 #define SPRITE_RENDER_H40(slot) \ 1912 #define SPRITE_RENDER_H40(slot) \
1790 case slot:\ 1913 case slot:\
1791 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\ 1914 if ((slot) == BG_START_SLOT + LINEBUF_SIZE/2) {\
1792 advance_output_line(context);\ 1915 advance_output_line(context);\
1916 }\
1917 if (slot == 168 || slot == 247 || slot == 248) {\
1918 render_border_garbage(\
1919 context,\
1920 context->sprite_draw_list[context->cur_slot].address,\
1921 context->tmp_buf_b,\
1922 context->buf_b_off + (slot == 247 ? 0 : 8),\
1923 slot == 247 ? context->col_1 : context->col_2\
1924 );\
1925 if (slot == 248) {\
1926 context->buf_a_off = (context->buf_a_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
1927 context->buf_b_off = (context->buf_b_off + SCROLL_BUFFER_DRAW) & SCROLL_BUFFER_MASK;\
1928 }\
1929 } else if (slot == 243) {\
1930 render_border_garbage(\
1931 context,\
1932 context->sprite_draw_list[context->cur_slot].address,\
1933 context->tmp_buf_a,\
1934 context->buf_a_off,\
1935 context->col_1\
1936 );\
1937 } else if (slot == 169) {\
1938 draw_right_border(context);\
1793 }\ 1939 }\
1794 render_sprite_cells( context);\ 1940 render_sprite_cells( context);\
1795 scan_sprite_table(context->vcounter, context);\ 1941 scan_sprite_table(context->vcounter, context);\
1796 CHECK_LIMIT_HSYNC(slot) 1942 CHECK_LIMIT_HSYNC(slot)
1797 1943
1910 *(dst++) = bg_color; 2056 *(dst++) = bg_color;
1911 } 2057 }
1912 } 2058 }
1913 context->sprite_index = 0x80; 2059 context->sprite_index = 0x80;
1914 context->slot_counter = 0; 2060 context->slot_counter = 0;
2061 render_border_garbage(
2062 context,
2063 context->sprite_draw_list[context->cur_slot].address,
2064 context->tmp_buf_b, context->buf_b_off,
2065 context->col_1
2066 );
1915 render_sprite_cells( context); 2067 render_sprite_cells( context);
1916 scan_sprite_table(context->vcounter, context); 2068 scan_sprite_table(context->vcounter, context);
1917 CHECK_LIMIT 2069 CHECK_LIMIT
1918 SPRITE_RENDER_H40(168) 2070 SPRITE_RENDER_H40(168)
1919 SPRITE_RENDER_H40(169) 2071 SPRITE_RENDER_H40(169)
1945 SPRITE_RENDER_H40(238) 2097 SPRITE_RENDER_H40(238)
1946 SPRITE_RENDER_H40(239) 2098 SPRITE_RENDER_H40(239)
1947 SPRITE_RENDER_H40(240) 2099 SPRITE_RENDER_H40(240)
1948 SPRITE_RENDER_H40(241) 2100 SPRITE_RENDER_H40(241)
1949 SPRITE_RENDER_H40(242) 2101 SPRITE_RENDER_H40(242)
1950 SPRITE_RENDER_H40(243) 2102 SPRITE_RENDER_H40(243) //provides "garbage" for border when plane A selected
1951 case 244: 2103 case 244:
1952 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 2104 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
1953 mask = 0; 2105 mask = 0;
1954 if (context->regs[REG_MODE_3] & 0x2) { 2106 if (context->regs[REG_MODE_3] & 0x2) {
1955 mask |= 0xF8; 2107 mask |= 0xF8;
1956 } 2108 }
1957 if (context->regs[REG_MODE_3] & 0x1) { 2109 if (context->regs[REG_MODE_3] & 0x1) {
1958 mask |= 0x7; 2110 mask |= 0x7;
1959 } 2111 }
2112 render_border_garbage(context, address, context->tmp_buf_a, context->buf_a_off+8, context->col_2);
1960 address += (context->vcounter & mask) * 4; 2113 address += (context->vcounter & mask) * 4;
1961 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1]; 2114 context->hscroll_a = context->vdpmem[address] << 8 | context->vdpmem[address+1];
1962 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3]; 2115 context->hscroll_b = context->vdpmem[address+2] << 8 | context->vdpmem[address+3];
1963 //printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b); 2116 //printf("%d: HScroll A: %d, HScroll B: %d\n", context->vcounter, context->hscroll_a, context->hscroll_b);
1964 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); } 2117 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, -1); }
1965 context->hslot++; 2118 context->hslot++;
1966 context->cycles += h40_hsync_cycles[14]; 2119 context->cycles += h40_hsync_cycles[14];
1967 CHECK_ONLY 2120 CHECK_ONLY //provides "garbage" for border when plane A selected
1968 //!HSYNC high 2121 //!HSYNC high
1969 SPRITE_RENDER_H40(245) 2122 SPRITE_RENDER_H40(245)
1970 SPRITE_RENDER_H40(246) 2123 SPRITE_RENDER_H40(246)
1971 SPRITE_RENDER_H40(247) 2124 SPRITE_RENDER_H40(247) //provides "garbage" for border when plane B selected
1972 SPRITE_RENDER_H40(248) 2125 SPRITE_RENDER_H40(248) //provides "garbage" for border when plane B selected
1973 case 249: 2126 case 249:
1974 read_map_scroll_a(0, context->vcounter, context); 2127 read_map_scroll_a(0, context->vcounter, context);
1975 CHECK_LIMIT 2128 CHECK_LIMIT
1976 SPRITE_RENDER_H40(250) 2129 SPRITE_RENDER_H40(250)
1977 case 251: 2130 case 251:
2035 } 2188 }
2036 //sprite render to line buffer starts 2189 //sprite render to line buffer starts
2037 case 163: 2190 case 163:
2038 context->cur_slot = MAX_DRAWS-1; 2191 context->cur_slot = MAX_DRAWS-1;
2039 memset(context->linebuf, 0, LINEBUF_SIZE); 2192 memset(context->linebuf, 0, LINEBUF_SIZE);
2193 render_border_garbage(
2194 context,
2195 context->sprite_draw_list[context->cur_slot].address,
2196 context->tmp_buf_a, context->buf_a_off,
2197 context->col_1
2198 );
2040 render_sprite_cells(context); 2199 render_sprite_cells(context);
2041 CHECK_LIMIT 2200 CHECK_LIMIT
2042 case 164: 2201 case 164:
2202 render_border_garbage(
2203 context,
2204 context->sprite_draw_list[context->cur_slot].address,
2205 context->tmp_buf_a, context->buf_a_off + 8,
2206 context->col_2
2207 );
2043 render_sprite_cells(context); 2208 render_sprite_cells(context);
2044 if (context->flags & FLAG_DMA_RUN) { 2209 if (context->flags & FLAG_DMA_RUN) {
2045 run_dma_src(context, -1); 2210 run_dma_src(context, -1);
2046 } 2211 }
2047 context->hslot++; 2212 context->hslot++;