Mercurial > repos > blastem
comparison vdp.c @ 1325:58bfbed6cdb5
Fairly major rework of how active/passive is handled along with how the V30 mode bit is handled. Allows the vertical border extension trick in Overdrive 2 to work right
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Fri, 21 Apr 2017 01:22:52 -0700 |
parents | b1423d432c0e |
children | 9bba5ff5beb8 |
comparison
equal
deleted
inserted
replaced
1324:2fc444b69351 | 1325:58bfbed6cdb5 |
---|---|
53 #define BORDER_BOT_V28_PAL 32 | 53 #define BORDER_BOT_V28_PAL 32 |
54 #define BORDER_BOT_V30_PAL 24 | 54 #define BORDER_BOT_V30_PAL 24 |
55 | 55 |
56 #define INVALID_LINE 0x200 | 56 #define INVALID_LINE 0x200 |
57 | 57 |
58 enum { | |
59 INACTIVE = 0, | |
60 PREPARING, //used for line 0x1FF | |
61 ACTIVE | |
62 }; | |
63 | |
58 static int32_t color_map[1 << 12]; | 64 static int32_t color_map[1 << 12]; |
59 static uint16_t mode4_address_map[0x4000]; | 65 static uint16_t mode4_address_map[0x4000]; |
60 static uint32_t planar_to_chunky[256]; | 66 static uint32_t planar_to_chunky[256]; |
61 static uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; | 67 static uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; |
62 | 68 |
69 }; | 75 }; |
70 | 76 |
71 static void update_video_params(vdp_context *context) | 77 static void update_video_params(vdp_context *context) |
72 { | 78 { |
73 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 79 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
74 if (context->latched_mode & BIT_PAL) { | 80 if (context->regs[REG_MODE_2] & BIT_PAL) { |
75 if (context->flags2 & FLAG2_REGION_PAL) { | 81 if (context->flags2 & FLAG2_REGION_PAL) { |
76 context->inactive_start = PAL_INACTIVE_START; | 82 context->inactive_start = PAL_INACTIVE_START; |
77 context->border_top = BORDER_TOP_V30_PAL; | 83 context->border_top = BORDER_TOP_V30_PAL; |
78 context->border_bot = BORDER_BOT_V30_PAL; | 84 context->border_bot = BORDER_BOT_V30_PAL; |
79 } else { | 85 } else { |
80 context->inactive_start = 0x200; | 86 //the behavior here is rather weird and needs more investigation |
81 context->border_top = context->border_bot = 0; | 87 context->inactive_start = 0xF0; |
88 context->border_top = 1; | |
89 context->border_bot = 3; | |
82 } | 90 } |
83 } else { | 91 } else { |
84 context->inactive_start = NTSC_INACTIVE_START; | 92 context->inactive_start = NTSC_INACTIVE_START; |
85 if (context->flags2 & FLAG2_REGION_PAL) { | 93 if (context->flags2 & FLAG2_REGION_PAL) { |
86 context->border_top = BORDER_TOP_V28_PAL; | 94 context->border_top = BORDER_TOP_V28_PAL; |
88 } else { | 96 } else { |
89 context->border_top = BORDER_TOP_V28; | 97 context->border_top = BORDER_TOP_V28; |
90 context->border_bot = BORDER_TOP_V28; | 98 context->border_bot = BORDER_TOP_V28; |
91 } | 99 } |
92 } | 100 } |
101 if (context->state == INACTIVE) { | |
102 //Undo forced INACTIVE state due to neither Mode 4 nor Mode 5 being active | |
103 if (context->vcounter < context->inactive_start) { | |
104 context->state = ACTIVE; | |
105 } else if (context->vcounter == 0x1FF) { | |
106 context->state = PREPARING; | |
107 } | |
108 } | |
93 } else { | 109 } else { |
94 context->inactive_start = MODE4_INACTIVE_START; | 110 context->inactive_start = MODE4_INACTIVE_START; |
95 if (context->flags2 & FLAG2_REGION_PAL) { | 111 if (context->flags2 & FLAG2_REGION_PAL) { |
96 context->border_top = BORDER_TOP_V24_PAL; | 112 context->border_top = BORDER_TOP_V24_PAL; |
97 context->border_bot = BORDER_BOT_V24_PAL; | 113 context->border_bot = BORDER_BOT_V24_PAL; |
98 } else { | 114 } else { |
99 context->border_top = BORDER_TOP_V24; | 115 context->border_top = BORDER_TOP_V24; |
100 context->border_bot = BORDER_BOT_V24; | 116 context->border_bot = BORDER_BOT_V24; |
117 } | |
118 if (!(context->regs[REG_MODE_1] & BIT_MODE_4)){ | |
119 context->state = INACTIVE; | |
120 } else if (context->state == INACTIVE) { | |
121 //Undo forced INACTIVE state due to neither Mode 4 nor Mode 5 being active | |
122 if (context->vcounter < context->inactive_start) { | |
123 context->state = ACTIVE; | |
124 } | |
125 /* | |
126 FIXME: uncomment this once mode 4 renderer is updated to handle this | |
127 else if (context->vcounter == 0x1FF) { | |
128 context->state = PREPARING; | |
129 } | |
130 */ | |
101 } | 131 } |
102 } | 132 } |
103 } | 133 } |
104 | 134 |
105 static uint8_t color_map_init_done; | 135 static uint8_t color_map_init_done; |
505 (context->flags2 & FLAG2_HINT_PENDING) ? "true" : "false", vdp_control_port_read(context)); | 535 (context->flags2 & FLAG2_HINT_PENDING) ? "true" : "false", vdp_control_port_read(context)); |
506 | 536 |
507 //TODO: Window Group, DMA Group | 537 //TODO: Window Group, DMA Group |
508 } | 538 } |
509 | 539 |
540 static uint8_t is_active(vdp_context *context) | |
541 { | |
542 return context->state != INACTIVE && (context->regs[REG_MODE_2] & BIT_DISP_EN) != 0; | |
543 } | |
544 | |
510 static void scan_sprite_table(uint32_t line, vdp_context * context) | 545 static void scan_sprite_table(uint32_t line, vdp_context * context) |
511 { | 546 { |
512 if (context->sprite_index && context->slot_counter) { | 547 if (context->sprite_index && context->slot_counter) { |
513 line += 1; | 548 line += 1; |
514 line &= 0xFF; | 549 line &= 0xFF; |
1199 } | 1234 } |
1200 | 1235 |
1201 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) | 1236 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) |
1202 { | 1237 { |
1203 uint32_t *dst; | 1238 uint32_t *dst; |
1204 if (line == 0x1FF) { | 1239 if (context->state == PREPARING) { |
1205 if (!col) { | 1240 if (!col) { |
1206 return; | 1241 return; |
1207 } | 1242 } |
1208 col -= 2; | 1243 col -= 2; |
1209 if (col) { | 1244 if (col) { |
1221 { | 1256 { |
1222 *(dst++) = color; | 1257 *(dst++) = color; |
1223 } | 1258 } |
1224 return; | 1259 return; |
1225 } | 1260 } |
1226 if (line >= 240) { | 1261 line &= 0xFF; |
1227 return; | |
1228 } | |
1229 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); | 1262 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); |
1230 uint8_t *sprite_buf, *plane_a, *plane_b; | 1263 uint8_t *sprite_buf, *plane_a, *plane_b; |
1231 int plane_a_off, plane_b_off; | 1264 int plane_a_off, plane_b_off; |
1232 if (col) | 1265 if (col) |
1233 { | 1266 { |
1303 //TODO: Simulate CRAM corruption from bus fight | 1336 //TODO: Simulate CRAM corruption from bus fight |
1304 switch (test_layer) | 1337 switch (test_layer) |
1305 { | 1338 { |
1306 case 1: | 1339 case 1: |
1307 pixel &= *sprite_buf; | 1340 pixel &= *sprite_buf; |
1341 if (output_disabled && pixel) { | |
1342 src = DBG_SRC_S; | |
1343 } | |
1308 break; | 1344 break; |
1309 case 2: | 1345 case 2: |
1310 pixel &= *plane_a; | 1346 pixel &= *plane_a; |
1347 if (output_disabled && pixel) { | |
1348 src = DBG_SRC_A; | |
1349 } | |
1311 break; | 1350 break; |
1312 case 3: | 1351 case 3: |
1313 pixel &= *plane_b; | 1352 pixel &= *plane_b; |
1353 if (output_disabled && pixel) { | |
1354 src = DBG_SRC_B; | |
1355 } | |
1314 break; | 1356 break; |
1315 } | 1357 } |
1316 | 1358 |
1317 uint32_t outpixel; | 1359 uint32_t outpixel; |
1318 if (context->debug) { | 1360 if (context->debug) { |
1347 //TODO: Simulate CRAM corruption from bus fight | 1389 //TODO: Simulate CRAM corruption from bus fight |
1348 switch (test_layer) | 1390 switch (test_layer) |
1349 { | 1391 { |
1350 case 1: | 1392 case 1: |
1351 pixel &= *sprite_buf; | 1393 pixel &= *sprite_buf; |
1394 if (output_disabled && pixel) { | |
1395 src = DBG_SRC_S; | |
1396 } | |
1352 break; | 1397 break; |
1353 case 2: | 1398 case 2: |
1354 pixel &= *plane_a; | 1399 pixel &= *plane_a; |
1400 if (output_disabled && pixel) { | |
1401 src = DBG_SRC_A; | |
1402 } | |
1355 break; | 1403 break; |
1356 case 3: | 1404 case 3: |
1357 pixel &= *plane_b; | 1405 pixel &= *plane_b; |
1406 if (output_disabled && pixel) { | |
1407 src = DBG_SRC_B; | |
1408 } | |
1358 break; | 1409 break; |
1359 } | 1410 } |
1360 uint32_t outpixel; | 1411 uint32_t outpixel; |
1361 if (context->debug) { | 1412 if (context->debug) { |
1362 outpixel = context->debugcolors[src]; | 1413 outpixel = context->debugcolors[src]; |
1537 context->vcounter++; | 1588 context->vcounter++; |
1538 | 1589 |
1539 uint8_t is_mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; | 1590 uint8_t is_mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; |
1540 if (is_mode_5) { | 1591 if (is_mode_5) { |
1541 if (context->flags2 & FLAG2_REGION_PAL) { | 1592 if (context->flags2 & FLAG2_REGION_PAL) { |
1542 if (context->latched_mode & BIT_PAL) { | 1593 if (context->regs[REG_MODE_2] & BIT_PAL) { |
1543 if (context->vcounter == 0x10B) { | 1594 if (context->vcounter == 0x10B) { |
1544 context->vcounter = 0x1D2; | 1595 context->vcounter = 0x1D2; |
1545 } | 1596 } |
1546 } else if (context->vcounter == 0x103){ | 1597 } else if (context->vcounter == 0x103){ |
1547 context->vcounter = 0x1CA; | 1598 context->vcounter = 0x1CA; |
1548 } | 1599 } |
1549 } else if (!(context->latched_mode & BIT_PAL) && context->vcounter == 0xEB) { | 1600 } else { |
1550 context->vcounter = 0x1E5; | 1601 if (context->regs[REG_MODE_2] & BIT_PAL) { |
1551 } | 1602 if (context->vcounter == 0x100) { |
1552 if (context->vcounter == 0x200 - context->border_top) { | 1603 context->vcounter = 0x1FA; |
1553 latch_mode(context); | 1604 } |
1605 } else if (context->vcounter == 0xEB) { | |
1606 context->vcounter = 0x1E5; | |
1607 } | |
1554 } | 1608 } |
1555 } else if (context->vcounter == 0xDB) { | 1609 } else if (context->vcounter == 0xDB) { |
1556 context->vcounter = 0x1D5; | 1610 context->vcounter = 0x1D5; |
1557 } | 1611 } |
1558 context->vcounter &= 0x1FF; | 1612 context->vcounter &= 0x1FF; |
1559 | 1613 if (context->state == PREPARING) { |
1560 if (context->vcounter > context->inactive_start) { | 1614 context->state = ACTIVE; |
1615 } | |
1616 | |
1617 if (context->state != ACTIVE) { | |
1561 context->hint_counter = context->regs[REG_HINT]; | 1618 context->hint_counter = context->regs[REG_HINT]; |
1562 } else if (context->hint_counter) { | 1619 } else if (context->hint_counter) { |
1563 context->hint_counter--; | 1620 context->hint_counter--; |
1564 } else { | 1621 } else { |
1565 context->flags2 |= FLAG2_HINT_PENDING; | 1622 context->flags2 |= FLAG2_HINT_PENDING; |
1574 if (context->vcounter == context->inactive_start) { | 1631 if (context->vcounter == context->inactive_start) { |
1575 context->frame++; | 1632 context->frame++; |
1576 } | 1633 } |
1577 context->vcounter &= 0x1FF; | 1634 context->vcounter &= 0x1FF; |
1578 } else { | 1635 } else { |
1579 if (context->vcounter == (context->inactive_start & 0x1FF)) { | 1636 uint16_t lines_max = (context->flags2 & FLAG2_REGION_PAL) |
1637 ? 240 + BORDER_TOP_V30_PAL + BORDER_BOT_V30_PAL | |
1638 : 224 + BORDER_TOP_V28 + BORDER_BOT_V28; | |
1639 | |
1640 if (context->output_lines == lines_max) { | |
1580 render_framebuffer_updated(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN: FRAMEBUFFER_ODD, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER)); | 1641 render_framebuffer_updated(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN: FRAMEBUFFER_ODD, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? LINEBUF_SIZE : (256+HORIZ_BORDER)); |
1581 if (context->double_res) { | 1642 if (context->double_res) { |
1582 context->flags2 ^= FLAG2_EVEN_FIELD; | 1643 context->flags2 ^= FLAG2_EVEN_FIELD; |
1583 } | 1644 } |
1584 context->fb = render_get_framebuffer(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD, &context->output_pitch); | 1645 context->fb = render_get_framebuffer(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD, &context->output_pitch); |
1585 context->h40_lines = 0; | 1646 context->h40_lines = 0; |
1586 context->frame++; | 1647 context->frame++; |
1648 context->output_lines = 0; | |
1587 } | 1649 } |
1588 uint32_t output_line; | 1650 uint32_t output_line; |
1589 if (context->vcounter < context->inactive_start + context->border_bot) { | 1651 if (context->vcounter < context->inactive_start + context->border_bot && context->output_lines > 0) { |
1590 output_line = context->border_top + context->vcounter; | 1652 output_line = context->output_lines++;//context->border_top + context->vcounter; |
1591 } else if (context->vcounter > 0x200 - context->border_top) { | 1653 } else if (context->vcounter >= 0x200 - context->border_top) { |
1592 output_line = context->vcounter - (0x200 - context->border_top); | 1654 output_line = context->output_lines++;//context->vcounter - (0x200 - context->border_top); |
1593 } else { | 1655 } else { |
1594 output_line = INVALID_LINE; | 1656 output_line = INVALID_LINE; |
1595 } | 1657 } |
1596 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); | 1658 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); |
1597 #ifdef DEBUG_FB_FILL | 1659 #ifdef DEBUG_FB_FILL |
1598 for (int i = 0; i < LINEBUF_SIZE; i++) | 1660 for (int i = 0; i < LINEBUF_SIZE; i++) |
1599 { | 1661 { |
1600 context->output[i] = 0xFFFF00FF; | 1662 context->output[i] = 0xFFFF00FF; |
1768 switch(context->hslot) | 1830 switch(context->hslot) |
1769 { | 1831 { |
1770 for (;;) | 1832 for (;;) |
1771 { | 1833 { |
1772 case 165: | 1834 case 165: |
1773 if (context->vcounter == 0x1FF) { | 1835 if (context->state == PREPARING) { |
1774 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 1836 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1775 uint32_t *dst; | 1837 uint32_t *dst; |
1776 if (headless) { | 1838 if (headless) { |
1777 dst = context->output; | 1839 dst = context->output; |
1778 } else { | 1840 } else { |
1785 } else { | 1847 } else { |
1786 render_sprite_cells(context); | 1848 render_sprite_cells(context); |
1787 } | 1849 } |
1788 CHECK_LIMIT | 1850 CHECK_LIMIT |
1789 case 166: | 1851 case 166: |
1790 if (context->vcounter == 0x1FF) { | 1852 if (context->state == PREPARING) { |
1791 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 1853 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1792 uint32_t *dst; | 1854 uint32_t *dst; |
1793 if (headless) { | 1855 if (headless) { |
1794 dst = context->output; | 1856 dst = context->output; |
1795 } else { | 1857 } else { |
1803 render_sprite_cells(context); | 1865 render_sprite_cells(context); |
1804 } | 1866 } |
1805 CHECK_LIMIT | 1867 CHECK_LIMIT |
1806 //sprite attribute table scan starts | 1868 //sprite attribute table scan starts |
1807 case 167: | 1869 case 167: |
1808 if (context->vcounter == 0x1FF) { | 1870 if (context->state == PREPARING) { |
1809 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 1871 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1810 uint32_t *dst; | 1872 uint32_t *dst; |
1811 if (headless) { | 1873 if (headless) { |
1812 dst = context->output; | 1874 dst = context->output; |
1813 } else { | 1875 } else { |
1975 switch(context->hslot) | 2037 switch(context->hslot) |
1976 { | 2038 { |
1977 for (;;) | 2039 for (;;) |
1978 { | 2040 { |
1979 case 133: | 2041 case 133: |
1980 if (context->vcounter == 0x1FF) { | 2042 if (context->state == PREPARING) { |
1981 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 2043 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1982 uint32_t *dst; | 2044 uint32_t *dst; |
1983 if (headless) { | 2045 if (headless) { |
1984 dst = context->output; | 2046 dst = context->output; |
1985 } else { | 2047 } else { |
1992 } else { | 2054 } else { |
1993 render_sprite_cells(context); | 2055 render_sprite_cells(context); |
1994 } | 2056 } |
1995 CHECK_LIMIT | 2057 CHECK_LIMIT |
1996 case 134: | 2058 case 134: |
1997 if (context->vcounter == 0x1FF) { | 2059 if (context->state == PREPARING) { |
1998 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 2060 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
1999 uint32_t *dst; | 2061 uint32_t *dst; |
2000 if (headless) { | 2062 if (headless) { |
2001 dst = context->output; | 2063 dst = context->output; |
2002 } else { | 2064 } else { |
2010 render_sprite_cells(context); | 2072 render_sprite_cells(context); |
2011 } | 2073 } |
2012 CHECK_LIMIT | 2074 CHECK_LIMIT |
2013 //sprite attribute table scan starts | 2075 //sprite attribute table scan starts |
2014 case 135: //FIXME - Here | 2076 case 135: //FIXME - Here |
2015 if (context->vcounter == 0x1FF) { | 2077 if (context->state == PREPARING) { |
2016 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; | 2078 uint32_t bg_color = context->colors[context->regs[REG_BG_COLOR] & 0x3F]; |
2017 uint32_t *dst; | 2079 uint32_t *dst; |
2018 if (headless) { | 2080 if (headless) { |
2019 dst = context->output; | 2081 dst = context->output; |
2020 } else { | 2082 } else { |
2286 context->hslot++; | 2348 context->hslot++; |
2287 context->cycles += MCLKS_SLOT_H32; | 2349 context->cycles += MCLKS_SLOT_H32; |
2288 } | 2350 } |
2289 } | 2351 } |
2290 | 2352 |
2291 void latch_mode(vdp_context * context) | |
2292 { | |
2293 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL; | |
2294 update_video_params(context); | |
2295 } | |
2296 | |
2297 static void vdp_inactive(vdp_context *context, uint32_t target_cycles, uint8_t is_h40, uint8_t mode_5) | 2353 static void vdp_inactive(vdp_context *context, uint32_t target_cycles, uint8_t is_h40, uint8_t mode_5) |
2298 { | 2354 { |
2299 uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest; | 2355 uint8_t buf_clear_slot, index_reset_slot, bg_end_slot, vint_slot, line_change, jump_start, jump_dest; |
2300 uint8_t index_reset_value, max_draws, max_sprites; | 2356 uint8_t index_reset_value, max_draws, max_sprites; |
2301 uint16_t vint_line, active_line; | 2357 uint16_t vint_line, active_line; |
2338 vint_slot = VINT_SLOT_MODE4; | 2394 vint_slot = VINT_SLOT_MODE4; |
2339 line_change = LINE_CHANGE_MODE4; | 2395 line_change = LINE_CHANGE_MODE4; |
2340 bg_color = render_map_color(0, 0, 0); | 2396 bg_color = render_map_color(0, 0, 0); |
2341 jump_start = 147; | 2397 jump_start = 147; |
2342 jump_dest = 233; | 2398 jump_dest = 233; |
2343 active_line = 0; | 2399 if (context->regs[REG_MODE_1] & BIT_MODE_4) { |
2400 //FIXME: This is actually 0x1FF like in Mode 5 | |
2401 active_line = 0; | |
2402 } else { | |
2403 //never active unless either mode 4 or mode 5 is turned on | |
2404 active_line = 0x200; | |
2405 } | |
2344 } | 2406 } |
2345 uint32_t *dst = ( | 2407 uint32_t *dst = ( |
2346 context->vcounter < context->inactive_start + context->border_bot | 2408 context->vcounter < context->inactive_start + context->border_bot |
2347 || context->vcounter > 0x200 - context->border_top | 2409 || context->vcounter > 0x200 - context->border_top |
2348 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot | 2410 ) && context->hslot >= BG_START_SLOT && context->hslot < bg_end_slot |
2412 context->hslot++; | 2474 context->hslot++; |
2413 } | 2475 } |
2414 if (context->hslot == line_change) { | 2476 if (context->hslot == line_change) { |
2415 vdp_advance_line(context); | 2477 vdp_advance_line(context); |
2416 if (context->vcounter == active_line) { | 2478 if (context->vcounter == active_line) { |
2479 context->state = PREPARING; | |
2417 return; | 2480 return; |
2418 } | 2481 } |
2419 } | 2482 } |
2420 } | 2483 } |
2421 } | 2484 } |
2424 { | 2487 { |
2425 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; | 2488 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; |
2426 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; | 2489 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; |
2427 while(context->cycles < target_cycles) | 2490 while(context->cycles < target_cycles) |
2428 { | 2491 { |
2429 uint8_t active_slot; | 2492 if (context->state == ACTIVE && context->vcounter == context->inactive_start) { |
2430 if (mode_5) { | 2493 context->state = INACTIVE; |
2431 //line 0x1FF is basically active even though it's not displayed | |
2432 active_slot = (context->vcounter < context->inactive_start || context->vcounter == 0x1FF) && (context->regs[REG_MODE_2] & DISPLAY_ENABLE); | |
2433 } else { | |
2434 //display is effectively disabled if neither mode 5 nor mode 4 are selected | |
2435 active_slot = context->vcounter < context->inactive_start && (context->regs[REG_MODE_2] & DISPLAY_ENABLE) && (context->regs[REG_MODE_1] & BIT_MODE_4); | |
2436 } | 2494 } |
2437 | 2495 |
2438 if (active_slot) { | 2496 if (is_active(context)) { |
2439 if (mode_5) { | 2497 if (mode_5) { |
2440 if (is_h40) { | 2498 if (is_h40) { |
2441 vdp_h40(context, target_cycles); | 2499 vdp_h40(context, target_cycles); |
2442 } else { | 2500 } else { |
2443 vdp_h32(context, target_cycles); | 2501 vdp_h32(context, target_cycles); |
2723 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; | 2781 context->flags2 &= ~FLAG2_SPRITE_COLLIDE; |
2724 } | 2782 } |
2725 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) { | 2783 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) { |
2726 value |= 0x10; | 2784 value |= 0x10; |
2727 } | 2785 } |
2728 uint32_t line= context->vcounter; | |
2729 uint32_t slot = context->hslot; | 2786 uint32_t slot = context->hslot; |
2730 if ((line >= context->inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { | 2787 if (!is_active(context)) { |
2731 value |= 0x8; | 2788 value |= 0x8; |
2732 } | 2789 } |
2733 if (context->regs[REG_MODE_4] & BIT_H40) { | 2790 if (context->regs[REG_MODE_4] & BIT_H40) { |
2734 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { | 2791 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { |
2735 value |= 0x4; | 2792 value |= 0x4; |
2854 } | 2911 } |
2855 } | 2912 } |
2856 } | 2913 } |
2857 } | 2914 } |
2858 | 2915 |
2859 static uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target) | 2916 static void get_jump_params(vdp_context *context, uint32_t *jump_start, uint32_t *jump_dst) |
2860 { | 2917 { |
2861 uint32_t jump_start, jump_dst; | |
2862 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 2918 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
2863 if (context->flags2 & FLAG2_REGION_PAL) { | 2919 if (context->flags2 & FLAG2_REGION_PAL) { |
2864 if (context->latched_mode & BIT_PAL) { | 2920 if (context->regs[REG_MODE_2] & BIT_PAL) { |
2865 jump_start = 0x10B; | 2921 *jump_start = 0x10B; |
2866 jump_dst = 0x1D2; | 2922 *jump_dst = 0x1D2; |
2867 } else { | 2923 } else { |
2868 jump_start = 0x103; | 2924 *jump_start = 0x103; |
2869 jump_dst = 0x1CA; | 2925 *jump_dst = 0x1CA; |
2870 } | 2926 } |
2871 } else { | 2927 } else { |
2872 if (context->latched_mode & BIT_PAL) { | 2928 if (context->regs[REG_MODE_2] & BIT_PAL) { |
2873 jump_start = 0; | 2929 *jump_start = 0x100; |
2874 jump_dst = 0; | 2930 *jump_dst = 0x1FA; |
2875 } else { | 2931 } else { |
2876 jump_start = 0xEB; | 2932 *jump_start = 0xEB; |
2877 jump_dst = 0x1E5; | 2933 *jump_dst = 0x1E5; |
2878 } | 2934 } |
2879 } | 2935 } |
2880 } else { | 2936 } else { |
2881 jump_start = 0xDB; | 2937 *jump_start = 0xDB; |
2882 jump_dst = 0x1D5; | 2938 *jump_dst = 0x1D5; |
2883 } | 2939 } |
2940 } | |
2941 | |
2942 static uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target) | |
2943 { | |
2944 uint32_t jump_start, jump_dst; | |
2945 get_jump_params(context, &jump_start, &jump_dst); | |
2884 uint32_t lines; | 2946 uint32_t lines; |
2885 if (context->vcounter < target) { | 2947 if (context->vcounter < target) { |
2886 if (target < jump_start) { | 2948 if (target < jump_start || context->vcounter > jump_start) { |
2887 lines = target - context->vcounter; | 2949 lines = target - context->vcounter; |
2888 } else { | 2950 } else { |
2889 lines = jump_start - context->vcounter + target - jump_dst; | 2951 lines = jump_start - context->vcounter + target - jump_dst; |
2890 } | 2952 } |
2891 } else { | 2953 } else { |
2915 } | 2977 } |
2916 if (context->flags2 & FLAG2_HINT_PENDING) { | 2978 if (context->flags2 & FLAG2_HINT_PENDING) { |
2917 return context->pending_hint_start; | 2979 return context->pending_hint_start; |
2918 } | 2980 } |
2919 uint32_t hint_line; | 2981 uint32_t hint_line; |
2920 if (context->vcounter + context->hint_counter >= context->inactive_start) { | 2982 if (context->state != ACTIVE) { |
2921 if (context->regs[REG_HINT] > context->inactive_start) { | 2983 hint_line = context->regs[REG_HINT]; |
2984 if (hint_line > context->inactive_start) { | |
2922 return 0xFFFFFFFF; | 2985 return 0xFFFFFFFF; |
2923 } | 2986 } |
2924 hint_line = context->regs[REG_HINT]; | |
2925 } else { | 2987 } else { |
2926 hint_line = context->vcounter + context->hint_counter + 1; | 2988 hint_line = context->vcounter + context->hint_counter + 1; |
2927 } | 2989 if (context->vcounter < context->inactive_start) { |
2928 | 2990 if (hint_line > context->inactive_start) { |
2991 hint_line = context->regs[REG_HINT]; | |
2992 if (hint_line > context->inactive_start) { | |
2993 return 0xFFFFFFFF; | |
2994 } | |
2995 } | |
2996 } else { | |
2997 uint32_t jump_start, jump_dst; | |
2998 get_jump_params(context, &jump_start, &jump_dst); | |
2999 if (hint_line >= jump_start && context->vcounter < jump_dst) { | |
3000 hint_line = (hint_line + jump_dst - jump_start) & 0x1FF; | |
3001 } | |
3002 if (hint_line < context->vcounter && hint_line > context->inactive_start) { | |
3003 return 0xFFFFFFFF; | |
3004 } | |
3005 } | |
3006 } | |
2929 return context->cycles + vdp_cycles_to_line(context, hint_line); | 3007 return context->cycles + vdp_cycles_to_line(context, hint_line); |
2930 } | 3008 } |
2931 | 3009 |
2932 static uint32_t vdp_next_vint_real(vdp_context * context) | 3010 static uint32_t vdp_next_vint_real(vdp_context * context) |
2933 { | 3011 { |