Mercurial > repos > blastem
comparison vdp.c @ 1167:e758ddbf0624
Initial work on emulating top and bottom border area
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 15 Jan 2017 15:07:24 -0800 |
parents | b251899f2b97 |
children | fa73a77ddf92 |
comparison
equal
deleted
inserted
replaced
1166:73e36dac5be7 | 1167:e758ddbf0624 |
---|---|
39 #define LINE_CHANGE_MODE4 249 | 39 #define LINE_CHANGE_MODE4 249 |
40 #define VBLANK_START_H40 (LINE_CHANGE_H40+2) | 40 #define VBLANK_START_H40 (LINE_CHANGE_H40+2) |
41 #define VBLANK_START_H32 (LINE_CHANGE_H32+2) | 41 #define VBLANK_START_H32 (LINE_CHANGE_H32+2) |
42 #define FIFO_LATENCY 3 | 42 #define FIFO_LATENCY 3 |
43 | 43 |
44 #define BORDER_TOP_V24 27 | |
45 #define BORDER_TOP_V28 11 | |
46 #define BORDER_TOP_V24_PAL 54 | |
47 #define BORDER_TOP_V28_PAL 38 | |
48 #define BORDER_TOP_V30_PAL 30 | |
49 | |
50 #define BORDER_BOT_V24 24 | |
51 #define BORDER_BOT_V28 8 | |
52 #define BORDER_BOT_V24_PAL 48 | |
53 #define BORDER_BOT_V28_PAL 32 | |
54 #define BORDER_BOT_V30_PAL 24 | |
55 | |
56 #define INVALID_LINE 0x200 | |
57 | |
44 static int32_t color_map[1 << 12]; | 58 static int32_t color_map[1 << 12]; |
45 static uint16_t mode4_address_map[0x4000]; | 59 static uint16_t mode4_address_map[0x4000]; |
46 static uint32_t planar_to_chunky[256]; | 60 static uint32_t planar_to_chunky[256]; |
47 static uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; | 61 static uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; |
48 | 62 |
51 {0, 0, 127}, //A | 65 {0, 0, 127}, //A |
52 {127, 0, 0}, //Window | 66 {127, 0, 0}, //Window |
53 {0, 127, 0}, //B | 67 {0, 127, 0}, //B |
54 {127, 0, 127} //Sprites | 68 {127, 0, 127} //Sprites |
55 }; | 69 }; |
70 | |
71 static void update_video_params(vdp_context *context) | |
72 { | |
73 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | |
74 if (context->latched_mode & BIT_PAL) { | |
75 if (context->flags2 & FLAG2_REGION_PAL) { | |
76 context->inactive_start = PAL_INACTIVE_START; | |
77 context->border_top = BORDER_TOP_V30_PAL; | |
78 context->border_bot = BORDER_BOT_V30_PAL; | |
79 } else { | |
80 context->inactive_start = 0x200; | |
81 context->border_top = context->border_bot = 0; | |
82 } | |
83 } else { | |
84 context->inactive_start = NTSC_INACTIVE_START; | |
85 if (context->flags2 & FLAG2_REGION_PAL) { | |
86 context->border_top = BORDER_TOP_V28_PAL; | |
87 context->border_bot = BORDER_BOT_V28_PAL; | |
88 } else { | |
89 context->border_top = BORDER_TOP_V28; | |
90 context->border_bot = BORDER_TOP_V28; | |
91 } | |
92 } | |
93 } else { | |
94 context->inactive_start = MODE4_INACTIVE_START; | |
95 if (context->flags2 & FLAG2_REGION_PAL) { | |
96 context->border_top = BORDER_TOP_V24_PAL; | |
97 context->border_bot = BORDER_BOT_V24_PAL; | |
98 } else { | |
99 context->border_top = BORDER_TOP_V24; | |
100 context->border_bot = BORDER_BOT_V24; | |
101 } | |
102 } | |
103 } | |
56 | 104 |
57 static uint8_t color_map_init_done; | 105 static uint8_t color_map_init_done; |
58 | 106 |
59 void init_vdp_context(vdp_context * context, uint8_t region_pal) | 107 void init_vdp_context(vdp_context * context, uint8_t region_pal) |
60 { | 108 { |
65 */ | 113 */ |
66 if (headless) { | 114 if (headless) { |
67 context->output = malloc(LINEBUF_SIZE); | 115 context->output = malloc(LINEBUF_SIZE); |
68 context->output_pitch = 0; | 116 context->output_pitch = 0; |
69 } else { | 117 } else { |
70 context->output = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); | 118 context->fb = render_get_framebuffer(FRAMEBUFFER_ODD, &context->output_pitch); |
71 } | 119 } |
72 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); | 120 context->linebuf = malloc(LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); |
73 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); | 121 memset(context->linebuf, 0, LINEBUF_SIZE + SCROLL_BUFFER_SIZE*2); |
74 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; | 122 context->tmp_buf_a = context->linebuf + LINEBUF_SIZE; |
75 context->tmp_buf_b = context->tmp_buf_a + SCROLL_BUFFER_SIZE; | 123 context->tmp_buf_b = context->tmp_buf_a + SCROLL_BUFFER_SIZE; |
160 context->debugcolors[color] = render_map_color(r, g, b); | 208 context->debugcolors[color] = render_map_color(r, g, b); |
161 } | 209 } |
162 } | 210 } |
163 if (region_pal) { | 211 if (region_pal) { |
164 context->flags2 |= FLAG2_REGION_PAL; | 212 context->flags2 |= FLAG2_REGION_PAL; |
213 } | |
214 update_video_params(context); | |
215 if (!headless) { | |
216 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * context->border_top); | |
165 } | 217 } |
166 } | 218 } |
167 | 219 |
168 void vdp_free(vdp_context *context) | 220 void vdp_free(vdp_context *context) |
169 { | 221 { |
1113 context->fetch_tmp[1] = context->vdpmem[address+1]; | 1165 context->fetch_tmp[1] = context->vdpmem[address+1]; |
1114 } | 1166 } |
1115 | 1167 |
1116 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) | 1168 static void render_map_output(uint32_t line, int32_t col, vdp_context * context) |
1117 { | 1169 { |
1170 uint32_t *dst; | |
1171 if (line == 0x1FF) { | |
1172 if (!col) { | |
1173 return; | |
1174 } | |
1175 col -= 2; | |
1176 dst = context->output + col * 8; | |
1177 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; | |
1178 for (int i = 0; i < 16; i++) | |
1179 { | |
1180 *(dst++) = color; | |
1181 } | |
1182 return; | |
1183 } | |
1118 if (line >= 240) { | 1184 if (line >= 240) { |
1119 return; | 1185 return; |
1120 } | 1186 } |
1121 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); | |
1122 uint32_t *dst; | |
1123 uint8_t *sprite_buf, *plane_a, *plane_b; | 1187 uint8_t *sprite_buf, *plane_a, *plane_b; |
1124 int plane_a_off, plane_b_off; | 1188 int plane_a_off, plane_b_off; |
1125 if (col) | 1189 if (col) |
1126 { | 1190 { |
1191 render_map(context->col_2, context->tmp_buf_b, context->buf_b_off+8, context); | |
1127 col-=2; | 1192 col-=2; |
1128 dst = context->output + col * 8; | 1193 dst = context->output + col * 8; |
1129 if (context->debug < 2) { | 1194 if (context->debug < 2) { |
1130 sprite_buf = context->linebuf + col * 8; | 1195 sprite_buf = context->linebuf + col * 8; |
1131 uint8_t a_src, src; | 1196 uint8_t a_src, src; |
1371 static uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19}; | 1436 static uint32_t const h40_hsync_cycles[] = {19, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 18, 20, 20, 20, 19}; |
1372 | 1437 |
1373 static void vdp_advance_line(vdp_context *context) | 1438 static void vdp_advance_line(vdp_context *context) |
1374 { | 1439 { |
1375 context->vcounter++; | 1440 context->vcounter++; |
1376 context->vcounter &= 0x1FF; | 1441 |
1377 uint8_t is_mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; | 1442 uint8_t is_mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; |
1378 if (is_mode_5) { | 1443 if (is_mode_5) { |
1379 if (context->flags2 & FLAG2_REGION_PAL) { | 1444 if (context->flags2 & FLAG2_REGION_PAL) { |
1380 if (context->latched_mode & BIT_PAL) { | 1445 if (context->latched_mode & BIT_PAL) { |
1381 if (context->vcounter == 0x10B) { | 1446 if (context->vcounter == 0x10B) { |
1388 context->vcounter = 0x1E5; | 1453 context->vcounter = 0x1E5; |
1389 } | 1454 } |
1390 } else if (context->vcounter == 0xDB) { | 1455 } else if (context->vcounter == 0xDB) { |
1391 context->vcounter = 0x1D5; | 1456 context->vcounter = 0x1D5; |
1392 } | 1457 } |
1393 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START); | 1458 if (headless) { |
1394 if (!is_mode_5) { | 1459 context->vcounter &= 0x1FF; |
1395 inactive_start = MODE4_INACTIVE_START; | 1460 } else { |
1396 } | 1461 if (context->vcounter == context->inactive_start) { |
1397 if (!headless) { | 1462 render_framebuffer_updated(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN: FRAMEBUFFER_ODD, context->h40_lines > (context->inactive_start + context->border_top) / 2 ? 320 : 256); |
1398 if (!context->vcounter && !context->output) { | |
1399 context->output = render_get_framebuffer(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD, &context->output_pitch); | |
1400 context->h40_lines = 0; | |
1401 } else if (context->vcounter == inactive_start) { //TODO: Change this once border emulation is added | |
1402 context->output = NULL; | |
1403 render_framebuffer_updated(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN: FRAMEBUFFER_ODD, context->h40_lines > inactive_start / 2 ? 320 : 256); | |
1404 if (context->double_res) { | 1463 if (context->double_res) { |
1405 context->flags2 ^= FLAG2_EVEN_FIELD; | 1464 context->flags2 ^= FLAG2_EVEN_FIELD; |
1406 } | 1465 } |
1407 } else if (context->output) { | 1466 context->fb = render_get_framebuffer(context->flags2 & FLAG2_EVEN_FIELD ? FRAMEBUFFER_EVEN : FRAMEBUFFER_ODD, &context->output_pitch); |
1408 context->output = (uint32_t *)(((char *)context->output) + context->output_pitch); | 1467 context->h40_lines = 0; |
1409 if (context->regs[REG_MODE_4] & BIT_H40) { | 1468 context->frame++; |
1410 context->h40_lines++; | 1469 } |
1411 } | 1470 context->vcounter &= 0x1FF; |
1412 } | 1471 uint32_t output_line; |
1413 } | 1472 if (context->vcounter < context->inactive_start + context->border_bot) { |
1414 | 1473 output_line = context->border_top + context->vcounter; |
1415 if (context->vcounter > inactive_start) { | 1474 } else if (context->vcounter > 0x200 - context->border_top) { |
1475 output_line = context->vcounter - (0x200 - context->border_top); | |
1476 } else { | |
1477 output_line = INVALID_LINE; | |
1478 } | |
1479 context->output = (uint32_t *)(((char *)context->fb) + context->output_pitch * output_line); | |
1480 if (output_line != INVALID_LINE && (context->regs[REG_MODE_4] & BIT_H40)) { | |
1481 context->h40_lines++; | |
1482 } | |
1483 } | |
1484 | |
1485 if (context->vcounter > context->inactive_start) { | |
1416 context->hint_counter = context->regs[REG_HINT]; | 1486 context->hint_counter = context->regs[REG_HINT]; |
1417 } else if (context->hint_counter) { | 1487 } else if (context->hint_counter) { |
1418 context->hint_counter--; | 1488 context->hint_counter--; |
1419 } else { | 1489 } else { |
1420 context->flags2 |= FLAG2_HINT_PENDING; | 1490 context->flags2 |= FLAG2_HINT_PENDING; |
1671 case 255: | 1741 case 255: |
1672 render_map_3(context); | 1742 render_map_3(context); |
1673 scan_sprite_table(context->vcounter, context);//Just a guess | 1743 scan_sprite_table(context->vcounter, context);//Just a guess |
1674 CHECK_LIMIT | 1744 CHECK_LIMIT |
1675 case 0: | 1745 case 0: |
1676 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { | 1746 if (context->vcounter == context->inactive_start) { |
1677 context->flags2 |= FLAG2_VINT_PENDING; | 1747 context->flags2 |= FLAG2_VINT_PENDING; |
1678 context->pending_vint_start = context->cycles; | 1748 context->pending_vint_start = context->cycles; |
1679 } | 1749 } |
1680 render_map_output(context->vcounter, 0, context); | 1750 render_map_output(context->vcounter, 0, context); |
1681 scan_sprite_table(context->vcounter, context);//Just a guess | 1751 scan_sprite_table(context->vcounter, context);//Just a guess |
1719 render_sprite_cells(context); | 1789 render_sprite_cells(context); |
1720 CHECK_LIMIT | 1790 CHECK_LIMIT |
1721 case 164: | 1791 case 164: |
1722 render_sprite_cells(context); | 1792 render_sprite_cells(context); |
1723 vdp_advance_line(context); | 1793 vdp_advance_line(context); |
1724 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { | 1794 if (context->vcounter == context->inactive_start) { |
1725 context->hslot++; | 1795 context->hslot++; |
1726 context->cycles += slot_cycles; | 1796 context->cycles += slot_cycles; |
1727 return; | 1797 return; |
1728 } | 1798 } |
1729 CHECK_LIMIT | 1799 CHECK_LIMIT |
1874 render_sprite_cells(context); | 1944 render_sprite_cells(context); |
1875 CHECK_LIMIT | 1945 CHECK_LIMIT |
1876 case 132: | 1946 case 132: |
1877 render_sprite_cells(context); | 1947 render_sprite_cells(context); |
1878 vdp_advance_line(context); | 1948 vdp_advance_line(context); |
1879 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { | 1949 if (context->vcounter == context->inactive_start) { |
1880 context->hslot++; | 1950 context->hslot++; |
1881 context->cycles += slot_cycles; | 1951 context->cycles += slot_cycles; |
1882 return; | 1952 return; |
1883 } | 1953 } |
1884 CHECK_LIMIT | 1954 CHECK_LIMIT |
2014 } | 2084 } |
2015 | 2085 |
2016 void latch_mode(vdp_context * context) | 2086 void latch_mode(vdp_context * context) |
2017 { | 2087 { |
2018 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL; | 2088 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL; |
2089 update_video_params(context); | |
2019 } | 2090 } |
2020 | 2091 |
2021 static void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) | 2092 static void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) |
2022 { | 2093 { |
2023 int starti = -1; | 2094 int starti = -1; |
2029 if (slot >= 11 && slot < 139) { | 2100 if (slot >= 11 && slot < 139) { |
2030 starti = (slot-11)*2; | 2101 starti = (slot-11)*2; |
2031 } | 2102 } |
2032 } | 2103 } |
2033 if (starti >= 0) { | 2104 if (starti >= 0) { |
2034 uint32_t color = context->colors[context->regs[REG_BG_COLOR]]; | 2105 uint32_t color = (context->regs[REG_MODE_2] & BIT_MODE_5) |
2106 ? context->colors[context->regs[REG_BG_COLOR]] | |
2107 : context->colors[CRAM_SIZE * 3 + 0x10 + (context->regs[REG_BG_COLOR] & 0xF)]; | |
2035 uint32_t * start = context->output + starti; | 2108 uint32_t * start = context->output + starti; |
2036 for (int i = 0; i < 2; i++) { | 2109 for (int i = 0; i < 2; i++) { |
2037 *(start++) = color; | 2110 *(start++) = color; |
2038 } | 2111 } |
2039 } | 2112 } |
2040 } | 2113 } |
2041 | 2114 |
2042 | 2115 |
2043 void vdp_run_context(vdp_context * context, uint32_t target_cycles) | 2116 void vdp_run_context(vdp_context * context, uint32_t target_cycles) |
2044 { | 2117 { |
2118 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; | |
2119 uint8_t mode_5 = context->regs[REG_MODE_2] & BIT_MODE_5; | |
2045 while(context->cycles < target_cycles) | 2120 while(context->cycles < target_cycles) |
2046 { | 2121 { |
2047 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; | 2122 uint8_t active_slot; |
2048 uint8_t active_slot, mode_5; | 2123 if (mode_5) { |
2049 uint32_t inactive_start; | |
2050 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | |
2051 //Mode 5 selected | |
2052 mode_5 = 1; | |
2053 inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START; | |
2054 //line 0x1FF is basically active even though it's not displayed | 2124 //line 0x1FF is basically active even though it's not displayed |
2055 active_slot = (context->vcounter < inactive_start || context->vcounter == 0x1FF) && (context->regs[REG_MODE_2] & DISPLAY_ENABLE); | 2125 active_slot = (context->vcounter < context->inactive_start || context->vcounter == 0x1FF) && (context->regs[REG_MODE_2] & DISPLAY_ENABLE); |
2056 } else { | 2126 } else { |
2057 mode_5 = 0; | |
2058 inactive_start = MODE4_INACTIVE_START; | |
2059 //display is effectively disabled if neither mode 5 nor mode 4 are selected | 2127 //display is effectively disabled if neither mode 5 nor mode 4 are selected |
2060 active_slot = context->vcounter < inactive_start && (context->regs[REG_MODE_2] & DISPLAY_ENABLE) && (context->regs[REG_MODE_1] & BIT_MODE_4); | 2128 active_slot = context->vcounter < context->inactive_start && (context->regs[REG_MODE_2] & DISPLAY_ENABLE) && (context->regs[REG_MODE_1] & BIT_MODE_4); |
2061 } | 2129 } |
2062 | 2130 |
2063 if (active_slot) { | 2131 if (active_slot) { |
2064 if (mode_5) { | 2132 if (mode_5) { |
2065 if (is_h40) { | 2133 if (is_h40) { |
2095 memset(context->linebuf, 0, LINEBUF_SIZE); | 2163 memset(context->linebuf, 0, LINEBUF_SIZE); |
2096 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1; | 2164 context->cur_slot = context->sprite_index = MAX_DRAWS_H32_MODE4-1; |
2097 context->sprite_draws = MAX_DRAWS_H32_MODE4; | 2165 context->sprite_draws = MAX_DRAWS_H32_MODE4; |
2098 } | 2166 } |
2099 } | 2167 } |
2100 if(context->vcounter == inactive_start) { | 2168 if(context->vcounter == context->inactive_start) { |
2101 uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32; | 2169 uint32_t intslot = context->regs[REG_MODE_4] & BIT_H40 ? VINT_SLOT_H40 : VINT_SLOT_H32; |
2102 if (context->hslot == intslot) { | 2170 if (context->hslot == intslot) { |
2103 context->flags2 |= FLAG2_VINT_PENDING; | 2171 context->flags2 |= FLAG2_VINT_PENDING; |
2104 context->pending_vint_start = context->cycles; | 2172 context->pending_vint_start = context->cycles; |
2105 } | 2173 } |
2117 inccycles = MCLKS_SLOT_H32; | 2185 inccycles = MCLKS_SLOT_H32; |
2118 } | 2186 } |
2119 if (!is_refresh(context, context->hslot)) { | 2187 if (!is_refresh(context, context->hslot)) { |
2120 external_slot(context); | 2188 external_slot(context); |
2121 } | 2189 } |
2122 if (context->vcounter < inactive_start) { | 2190 if (context->vcounter < (context->inactive_start + context->border_bot) || context->vcounter > 0x200 - context->border_top) { |
2123 check_render_bg(context, context->vcounter, context->hslot); | 2191 check_render_bg(context, context->vcounter, context->hslot); |
2124 } | 2192 } |
2125 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, context->hslot)) { | 2193 if (context->flags & FLAG_DMA_RUN && !is_refresh(context, context->hslot)) { |
2126 run_dma_src(context, context->hslot); | 2194 run_dma_src(context, context->hslot); |
2127 } | 2195 } |
2128 context->cycles += inccycles; | 2196 context->cycles += inccycles; |
2129 context->hslot++; | 2197 context->hslot++; |
2130 if (is_h40) { | 2198 if (is_h40) { |
2131 if (context->hslot == LINE_CHANGE_H40) { | 2199 if (context->hslot == LINE_CHANGE_H40) { |
2132 vdp_advance_line(context); | 2200 vdp_advance_line(context); |
2133 if (context->vcounter == (inactive_start + 8)) { | |
2134 context->frame++; | |
2135 } | |
2136 } else if (context->hslot == 183) { | 2201 } else if (context->hslot == 183) { |
2137 context->hslot = 229; | 2202 context->hslot = 229; |
2138 } | 2203 } |
2139 } else { | 2204 } else { |
2140 if (context->hslot == (mode_5 ? LINE_CHANGE_H32 : LINE_CHANGE_MODE4)) { | 2205 if (context->hslot == (mode_5 ? LINE_CHANGE_H32 : LINE_CHANGE_MODE4)) { |
2141 vdp_advance_line(context); | 2206 vdp_advance_line(context); |
2142 if (context->vcounter == (inactive_start + 8)) { | |
2143 context->frame++; | |
2144 } | |
2145 } else if (context->hslot == 148) { | 2207 } else if (context->hslot == 148) { |
2146 context->hslot = 233; | 2208 context->hslot = 233; |
2147 } | 2209 } |
2148 } | 2210 } |
2149 } | 2211 } |
2150 } | 2212 } |
2151 } | 2213 } |
2152 | 2214 |
2153 uint32_t vdp_run_to_vblank(vdp_context * context) | 2215 uint32_t vdp_run_to_vblank(vdp_context * context) |
2154 { | 2216 { |
2155 uint32_t target_cycles = ((context->latched_mode & BIT_PAL) ? PAL_INACTIVE_START : NTSC_INACTIVE_START) * MCLKS_LINE; | 2217 uint32_t old_frame = context->frame; |
2156 vdp_run_context(context, target_cycles); | 2218 while (context->frame == old_frame) { |
2219 vdp_run_context(context, MCLKS_LINE); | |
2220 } | |
2157 return context->cycles; | 2221 return context->cycles; |
2158 } | 2222 } |
2159 | 2223 |
2160 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) | 2224 void vdp_run_dma_done(vdp_context * context, uint32_t target_cycles) |
2161 { | 2225 { |
2273 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); | 2337 context->double_res = (value & (BIT_INTERLACE | BIT_DOUBLE_RES)) == (BIT_INTERLACE | BIT_DOUBLE_RES); |
2274 if (!context->double_res) { | 2338 if (!context->double_res) { |
2275 context->flags2 &= ~FLAG2_EVEN_FIELD; | 2339 context->flags2 &= ~FLAG2_EVEN_FIELD; |
2276 } | 2340 } |
2277 } | 2341 } |
2342 if (reg == REG_MODE_2) { | |
2343 update_video_params(context); | |
2344 } | |
2278 } | 2345 } |
2279 } else if (mode_5) { | 2346 } else if (mode_5) { |
2280 context->flags |= FLAG_PENDING; | 2347 context->flags |= FLAG_PENDING; |
2281 //Should these be taken care of here or after the second write? | 2348 //Should these be taken care of here or after the second write? |
2282 //context->flags &= ~FLAG_READ_FETCHED; | 2349 //context->flags &= ~FLAG_READ_FETCHED; |
2410 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) { | 2477 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && !(context->flags2 & FLAG2_EVEN_FIELD)) { |
2411 value |= 0x10; | 2478 value |= 0x10; |
2412 } | 2479 } |
2413 uint32_t line= context->vcounter; | 2480 uint32_t line= context->vcounter; |
2414 uint32_t slot = context->hslot; | 2481 uint32_t slot = context->hslot; |
2415 uint32_t inactive_start = (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START); | 2482 if ((line >= context->inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { |
2416 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { | |
2417 inactive_start = MODE4_INACTIVE_START; | |
2418 } | |
2419 if ((line >= inactive_start && line < 0x1FF) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { | |
2420 value |= 0x8; | 2483 value |= 0x8; |
2421 } | 2484 } |
2422 if (context->regs[REG_MODE_4] & BIT_H40) { | 2485 if (context->regs[REG_MODE_4] & BIT_H40) { |
2423 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { | 2486 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { |
2424 value |= 0x4; | 2487 value |= 0x4; |
2590 } | 2653 } |
2591 } | 2654 } |
2592 return MCLKS_LINE * (lines - 1) + vdp_cycles_next_line(context); | 2655 return MCLKS_LINE * (lines - 1) + vdp_cycles_next_line(context); |
2593 } | 2656 } |
2594 | 2657 |
2595 static uint32_t vdp_frame_end_line(vdp_context * context) | |
2596 { | |
2597 uint32_t frame_end; | |
2598 if (context->flags2 & FLAG2_REGION_PAL) { | |
2599 if (context->latched_mode & BIT_PAL) { | |
2600 frame_end = PAL_INACTIVE_START + 8; | |
2601 } else { | |
2602 frame_end = NTSC_INACTIVE_START + 8; | |
2603 } | |
2604 } else { | |
2605 if (context->latched_mode & BIT_PAL) { | |
2606 frame_end = 512; | |
2607 } else { | |
2608 frame_end = NTSC_INACTIVE_START + 8; | |
2609 } | |
2610 } | |
2611 return frame_end; | |
2612 } | |
2613 | |
2614 uint32_t vdp_cycles_to_frame_end(vdp_context * context) | 2658 uint32_t vdp_cycles_to_frame_end(vdp_context * context) |
2615 { | 2659 { |
2616 return context->cycles + vdp_cycles_to_line(context, vdp_frame_end_line(context)); | 2660 return context->cycles + vdp_cycles_to_line(context, context->inactive_start); |
2617 } | 2661 } |
2618 | 2662 |
2619 uint32_t vdp_next_hint(vdp_context * context) | 2663 uint32_t vdp_next_hint(vdp_context * context) |
2620 { | 2664 { |
2621 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { | 2665 if (!(context->regs[REG_MODE_1] & BIT_HINT_EN)) { |
2622 return 0xFFFFFFFF; | 2666 return 0xFFFFFFFF; |
2623 } | 2667 } |
2624 if (context->flags2 & FLAG2_HINT_PENDING) { | 2668 if (context->flags2 & FLAG2_HINT_PENDING) { |
2625 return context->pending_hint_start; | 2669 return context->pending_hint_start; |
2626 } | 2670 } |
2627 uint32_t inactive_start = (context->regs[REG_MODE_2] & BIT_MODE_5) | |
2628 ? (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START) | |
2629 : MODE4_INACTIVE_START; | |
2630 uint32_t hint_line; | 2671 uint32_t hint_line; |
2631 if (context->vcounter + context->hint_counter >= inactive_start) { | 2672 if (context->vcounter + context->hint_counter >= context->inactive_start) { |
2632 if (context->regs[REG_HINT] > inactive_start) { | 2673 if (context->regs[REG_HINT] > context->inactive_start) { |
2633 return 0xFFFFFFFF; | 2674 return 0xFFFFFFFF; |
2634 } | 2675 } |
2635 hint_line = context->regs[REG_HINT]; | 2676 hint_line = context->regs[REG_HINT]; |
2636 } else { | 2677 } else { |
2637 hint_line = context->vcounter + context->hint_counter + 1; | 2678 hint_line = context->vcounter + context->hint_counter + 1; |
2653 return vdp_next_vint_z80(context); | 2694 return vdp_next_vint_z80(context); |
2654 } | 2695 } |
2655 | 2696 |
2656 uint32_t vdp_next_vint_z80(vdp_context * context) | 2697 uint32_t vdp_next_vint_z80(vdp_context * context) |
2657 { | 2698 { |
2658 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START; | 2699 if (context->vcounter == context->inactive_start) { |
2659 if (!(context->regs[REG_MODE_2] & BIT_MODE_5)) { | |
2660 inactive_start = MODE4_INACTIVE_START; | |
2661 } | |
2662 if (context->vcounter == inactive_start) { | |
2663 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 2700 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
2664 if (context->regs[REG_MODE_4] & BIT_H40) { | 2701 if (context->regs[REG_MODE_4] & BIT_H40) { |
2665 if (context->hslot >= LINE_CHANGE_H40 && context->hslot <= VINT_SLOT_H40) { | 2702 if (context->hslot >= LINE_CHANGE_H40 && context->hslot <= VINT_SLOT_H40) { |
2666 uint32_t cycles = context->cycles; | 2703 uint32_t cycles = context->cycles; |
2667 if (context->hslot < 182) { | 2704 if (context->hslot < 182) { |
2694 if (context->hslot <= VINT_SLOT_MODE4) { | 2731 if (context->hslot <= VINT_SLOT_MODE4) { |
2695 return context->cycles + (VINT_SLOT_MODE4 - context->hslot) * MCLKS_SLOT_H32; | 2732 return context->cycles + (VINT_SLOT_MODE4 - context->hslot) * MCLKS_SLOT_H32; |
2696 } | 2733 } |
2697 } | 2734 } |
2698 } | 2735 } |
2699 int32_t cycles_to_vint = vdp_cycles_to_line(context, inactive_start); | 2736 int32_t cycles_to_vint = vdp_cycles_to_line(context, context->inactive_start); |
2700 if (context->regs[REG_MODE_2] & BIT_MODE_5) { | 2737 if (context->regs[REG_MODE_2] & BIT_MODE_5) { |
2701 if (context->regs[REG_MODE_4] & BIT_H40) { | 2738 if (context->regs[REG_MODE_4] & BIT_H40) { |
2702 cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 + (256 - VINT_SLOT_H40)) * MCLKS_SLOT_H40; | 2739 cycles_to_vint += MCLKS_LINE - (LINE_CHANGE_H40 + (256 - VINT_SLOT_H40)) * MCLKS_SLOT_H40; |
2703 } else { | 2740 } else { |
2704 cycles_to_vint += (VINT_SLOT_H32 - 233 + 148 - LINE_CHANGE_H32) * MCLKS_SLOT_H32; | 2741 cycles_to_vint += (VINT_SLOT_H32 - 233 + 148 - LINE_CHANGE_H32) * MCLKS_SLOT_H32; |