Mercurial > repos > blastem
comparison vdp.c @ 647:5d58dcd94733
Fix the HV counter and adjust the slots of certain VDP events
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 14 Dec 2014 18:14:50 -0800 |
parents | 9089951a1994 |
children | a7971650c04e |
comparison
equal
deleted
inserted
replaced
646:fa345ce3e5bd | 647:5d58dcd94733 |
---|---|
25 #define VINT_SLOT_H40 4 //21 slots before HSYNC, 16 during, 10 after | 25 #define VINT_SLOT_H40 4 //21 slots before HSYNC, 16 during, 10 after |
26 #define VINT_SLOT_H32 23 //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number | 26 #define VINT_SLOT_H32 23 //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number |
27 #define HSYNC_SLOT_H40 240 | 27 #define HSYNC_SLOT_H40 240 |
28 #define HSYNC_END_H40 (240+17) | 28 #define HSYNC_END_H40 (240+17) |
29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32) | 29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32) |
30 #define HBLANK_START_H40 167 | 30 #define HBLANK_START_H40 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results |
31 #define HBLANK_END_H40 11 //should be 10.25 according to Nemesis IIRC | 31 #define HBLANK_END_H40 0 //should be 5.5 according to Nemesis, but 0 seems to fit better with my test ROM results |
32 #define HBLANK_START_H32 134 | 32 #define HBLANK_START_H32 233 //should be 147 according to Nemesis which is very different from my test ROM result |
33 #define HBLANK_END_H32 8 //should be 7.5 according to Nemesis IIRC | 33 #define HBLANK_END_H32 0 //should be 5 according to Nemesis, but 0 seems to fit better with my test ROM results |
34 #define LINE_CHANGE_H40 165 | |
35 #define LINE_CHANGE_H32 132 | |
34 #define FIFO_LATENCY 3 | 36 #define FIFO_LATENCY 3 |
35 | 37 |
36 int32_t color_map[1 << 12]; | 38 int32_t color_map[1 << 12]; |
37 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; | 39 uint8_t levels[] = {0, 27, 49, 71, 87, 103, 119, 130, 146, 157, 174, 190, 206, 228, 255}; |
38 | 40 |
258 context->regs[REG_DMASRC_H] << 17 | context->regs[REG_DMASRC_M] << 9 | context->regs[REG_DMASRC_L] << 1, | 260 context->regs[REG_DMASRC_H] << 17 | context->regs[REG_DMASRC_M] << 9 | context->regs[REG_DMASRC_L] << 1, |
259 src_types[context->regs[REG_DMASRC_H] >> 6 & 3]); | 261 src_types[context->regs[REG_DMASRC_H] >> 6 & 3]); |
260 printf("\n**Internal Group**\n" | 262 printf("\n**Internal Group**\n" |
261 "Address: %X\n" | 263 "Address: %X\n" |
262 "CD: %X\n" | 264 "CD: %X\n" |
263 "Pending: %s\n", | 265 "Pending: %s\n" |
264 context->address, context->cd, (context->flags & FLAG_PENDING) ? "true" : "false"); | 266 "VCounter: %d\n" |
267 "HCounter: %d\n", | |
268 context->address, context->cd, (context->flags & FLAG_PENDING) ? "true" : "false", | |
269 context->vcounter, context->hslot*2); | |
265 | 270 |
266 //TODO: Window Group, DMA Group | 271 //TODO: Window Group, DMA Group |
267 } | 272 } |
268 | 273 |
269 void scan_sprite_table(uint32_t line, vdp_context * context) | 274 void scan_sprite_table(uint32_t line, vdp_context * context) |
909 { | 914 { |
910 uint16_t address; | 915 uint16_t address; |
911 uint32_t mask; | 916 uint32_t mask; |
912 switch(linecyc) | 917 switch(linecyc) |
913 { | 918 { |
919 case 165: | |
920 case 166: | |
921 external_slot(context); | |
922 break; | |
914 //sprite render to line buffer starts | 923 //sprite render to line buffer starts |
915 case 167: | 924 case 167: |
916 context->cur_slot = MAX_DRAWS-1; | |
917 memset(context->linebuf, 0, LINEBUF_SIZE); | |
918 case 168: | 925 case 168: |
919 case 169: | 926 case 169: |
920 case 170: | 927 case 170: |
921 if (line == 0xFF) { | 928 if (line == 0xFF) { |
922 external_slot(context); | 929 external_slot(context); |
925 } | 932 } |
926 break; | 933 break; |
927 //sprite attribute table scan starts | 934 //sprite attribute table scan starts |
928 case 171: | 935 case 171: |
929 render_sprite_cells( context); | 936 render_sprite_cells( context); |
930 context->sprite_index = 0x80; | |
931 context->slot_counter = MAX_SPRITES_LINE; | |
932 scan_sprite_table(line, context); | 937 scan_sprite_table(line, context); |
933 break; | 938 break; |
934 case 172: | 939 case 172: |
935 case 173: | 940 case 173: |
936 case 174: | 941 case 174: |
1047 COLUMN_RENDER_BLOCK_REFRESH(32, 125) | 1052 COLUMN_RENDER_BLOCK_REFRESH(32, 125) |
1048 COLUMN_RENDER_BLOCK(34, 133) | 1053 COLUMN_RENDER_BLOCK(34, 133) |
1049 COLUMN_RENDER_BLOCK(36, 141) | 1054 COLUMN_RENDER_BLOCK(36, 141) |
1050 COLUMN_RENDER_BLOCK(38, 149) | 1055 COLUMN_RENDER_BLOCK(38, 149) |
1051 COLUMN_RENDER_BLOCK_REFRESH(40, 157) | 1056 COLUMN_RENDER_BLOCK_REFRESH(40, 157) |
1052 case 165: | |
1053 case 166: | |
1054 external_slot(context); | |
1055 break; | |
1056 } | 1057 } |
1057 } | 1058 } |
1058 | 1059 |
1059 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) | 1060 void vdp_h32(uint32_t line, uint32_t linecyc, vdp_context * context) |
1060 { | 1061 { |
1061 uint16_t address; | 1062 uint16_t address; |
1062 uint32_t mask; | 1063 uint32_t mask; |
1063 switch(linecyc) | 1064 switch(linecyc) |
1064 { | 1065 { |
1066 case 132: | |
1067 case 133: | |
1068 external_slot(context); | |
1069 break; | |
1065 //sprite render to line buffer starts | 1070 //sprite render to line buffer starts |
1066 case 134: | 1071 case 134: |
1067 context->cur_slot = MAX_DRAWS_H32-1; | |
1068 memset(context->linebuf, 0, LINEBUF_SIZE); | |
1069 case 135: | 1072 case 135: |
1070 case 136: | 1073 case 136: |
1071 case 137: | 1074 case 137: |
1072 if (line == 0xFF) { | 1075 if (line == 0xFF) { |
1073 external_slot(context); | 1076 external_slot(context); |
1076 } | 1079 } |
1077 break; | 1080 break; |
1078 //sprite attribute table scan starts | 1081 //sprite attribute table scan starts |
1079 case 138: | 1082 case 138: |
1080 render_sprite_cells( context); | 1083 render_sprite_cells( context); |
1081 context->sprite_index = 0x80; | |
1082 context->slot_counter = MAX_SPRITES_LINE_H32; | |
1083 scan_sprite_table(line, context); | 1084 scan_sprite_table(line, context); |
1084 break; | 1085 break; |
1085 case 139: | 1086 case 139: |
1086 case 140: | 1087 case 140: |
1087 case 141: | 1088 case 141: |
1188 COLUMN_RENDER_BLOCK_REFRESH(24, 92) | 1189 COLUMN_RENDER_BLOCK_REFRESH(24, 92) |
1189 COLUMN_RENDER_BLOCK(26, 100) | 1190 COLUMN_RENDER_BLOCK(26, 100) |
1190 COLUMN_RENDER_BLOCK(28, 108) | 1191 COLUMN_RENDER_BLOCK(28, 108) |
1191 COLUMN_RENDER_BLOCK(30, 116) | 1192 COLUMN_RENDER_BLOCK(30, 116) |
1192 COLUMN_RENDER_BLOCK_REFRESH(32, 124) | 1193 COLUMN_RENDER_BLOCK_REFRESH(32, 124) |
1193 case 132: | |
1194 case 133: | |
1195 external_slot(context); | |
1196 break; | |
1197 } | 1194 } |
1198 } | 1195 } |
1199 | 1196 |
1200 void vdp_h40_line(uint32_t line, vdp_context * context) | 1197 void vdp_h40_line(uint32_t line, vdp_context * context) |
1201 { | 1198 { |
1202 context->cur_slot = MAX_DRAWS-1; | 1199 context->cur_slot = MAX_DRAWS-1; |
1203 memset(context->linebuf, 0, LINEBUF_SIZE); | 1200 memset(context->linebuf, 0, LINEBUF_SIZE); |
1204 if (line == 0xFF) { | 1201 if (line == 0xFF) { |
1202 external_slot(context); | |
1203 if (context->flags & FLAG_DMA_RUN) { | |
1204 run_dma_src(context, 0); | |
1205 } | |
1206 external_slot(context); | |
1207 if (context->flags & FLAG_DMA_RUN) { | |
1208 run_dma_src(context, 0); | |
1209 } | |
1205 external_slot(context); | 1210 external_slot(context); |
1206 if (context->flags & FLAG_DMA_RUN) { | 1211 if (context->flags & FLAG_DMA_RUN) { |
1207 run_dma_src(context, 0); | 1212 run_dma_src(context, 0); |
1208 } | 1213 } |
1209 external_slot(context); | 1214 external_slot(context); |
1253 } | 1258 } |
1254 read_sprite_x(line, context); | 1259 read_sprite_x(line, context); |
1255 | 1260 |
1256 read_sprite_x(line, context); | 1261 read_sprite_x(line, context); |
1257 } | 1262 } |
1258 external_slot(context); | 1263 |
1259 if (context->flags & FLAG_DMA_RUN) { | |
1260 run_dma_src(context, 0); | |
1261 } | |
1262 external_slot(context); | |
1263 return; | 1264 return; |
1265 } | |
1266 external_slot(context); | |
1267 if (context->flags & FLAG_DMA_RUN) { | |
1268 run_dma_src(context, 0); | |
1269 } | |
1270 external_slot(context); | |
1271 if (context->flags & FLAG_DMA_RUN) { | |
1272 run_dma_src(context, 0); | |
1264 } | 1273 } |
1265 | 1274 |
1266 render_sprite_cells(context); | 1275 render_sprite_cells(context); |
1267 render_sprite_cells(context); | 1276 render_sprite_cells(context); |
1268 render_sprite_cells(context); | 1277 render_sprite_cells(context); |
1369 read_map_scroll_b(column, line, context); | 1378 read_map_scroll_b(column, line, context); |
1370 read_sprite_x(line, context); | 1379 read_sprite_x(line, context); |
1371 render_map_3(context); | 1380 render_map_3(context); |
1372 render_map_output(line, column, context); | 1381 render_map_output(line, column, context); |
1373 } | 1382 } |
1374 external_slot(context); | |
1375 if (context->flags & FLAG_DMA_RUN) { | |
1376 run_dma_src(context, 0); | |
1377 } | |
1378 external_slot(context); | |
1379 } | 1383 } |
1380 | 1384 |
1381 void latch_mode(vdp_context * context) | 1385 void latch_mode(vdp_context * context) |
1382 { | 1386 { |
1383 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL; | 1387 context->latched_mode = context->regs[REG_MODE_2] & BIT_PAL; |
1428 uint32_t slot = context->hslot; | 1432 uint32_t slot = context->hslot; |
1429 //TODO: Figure out when this actually happens | 1433 //TODO: Figure out when this actually happens |
1430 if (!line && !slot) { | 1434 if (!line && !slot) { |
1431 latch_mode(context); | 1435 latch_mode(context); |
1432 } | 1436 } |
1437 | |
1433 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; | 1438 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; |
1434 if (is_h40 && slot == HBLANK_START_H40 || !is_h40 && slot == 134) { | 1439 if (is_h40) { |
1440 if (slot == 167) { | |
1441 context->cur_slot = MAX_DRAWS-1; | |
1442 memset(context->linebuf, 0, LINEBUF_SIZE); | |
1443 } else if (slot == 171) { | |
1444 context->sprite_index = 0x80; | |
1445 context->slot_counter = MAX_SPRITES_LINE; | |
1446 } | |
1447 } else { | |
1448 if (slot == 134) { | |
1449 context->cur_slot = MAX_DRAWS_H32-1; | |
1450 memset(context->linebuf, 0, LINEBUF_SIZE); | |
1451 } else if (slot == 138) { | |
1452 context->sprite_index = 0x80; | |
1453 context->slot_counter = MAX_SPRITES_LINE_H32; | |
1454 } | |
1455 } | |
1456 if (is_h40 && slot == LINE_CHANGE_H40 || !is_h40 && slot == LINE_CHANGE_H32) { | |
1435 if (line >= inactive_start) { | 1457 if (line >= inactive_start) { |
1436 context->hint_counter = context->regs[REG_HINT]; | 1458 context->hint_counter = context->regs[REG_HINT]; |
1437 } else if (context->hint_counter) { | 1459 } else if (context->hint_counter) { |
1438 context->hint_counter--; | 1460 context->hint_counter--; |
1439 } else { | 1461 } else { |
1468 } | 1490 } |
1469 uint8_t inc_slot = 1; | 1491 uint8_t inc_slot = 1; |
1470 if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) { | 1492 if (context->regs[REG_MODE_2] & DISPLAY_ENABLE && active_slot) { |
1471 //run VDP rendering for a slot or a line | 1493 //run VDP rendering for a slot or a line |
1472 if (is_h40) { | 1494 if (is_h40) { |
1473 if (slot == HBLANK_START_H40 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) { | 1495 if (slot == LINE_CHANGE_H40 && line < inactive_start && (target_cycles - context->cycles) >= MCLKS_LINE) { |
1474 vdp_h40_line(line, context); | 1496 vdp_h40_line(line, context); |
1475 inccycles = MCLKS_LINE; | 1497 inccycles = MCLKS_LINE; |
1476 context->vcounter++; | 1498 context->vcounter++; |
1477 inc_slot = 0; | 1499 inc_slot = 0; |
1478 } else { | 1500 } else { |
1494 } | 1516 } |
1495 if (inc_slot) { | 1517 if (inc_slot) { |
1496 context->hslot++; | 1518 context->hslot++; |
1497 context->hslot &= 0xFF; | 1519 context->hslot &= 0xFF; |
1498 if (is_h40) { | 1520 if (is_h40) { |
1499 if (context->hslot == HBLANK_START_H40) { | 1521 if (context->hslot == LINE_CHANGE_H40) { |
1500 context->vcounter++; | 1522 context->vcounter++; |
1501 } else if (context->hslot == 183) { | 1523 } else if (context->hslot == 183) { |
1502 context->hslot = 229; | 1524 context->hslot = 229; |
1503 } | 1525 } |
1504 } else { | 1526 } else { |
1505 if (context->hslot == 134) { | 1527 if (context->hslot == LINE_CHANGE_H32) { |
1506 context->vcounter++; | 1528 context->vcounter++; |
1507 } else if (context->hslot == 148) { | 1529 } else if (context->hslot == 148) { |
1508 context->hslot = 233; | 1530 context->hslot = 233; |
1509 } | 1531 } |
1510 } | 1532 } |
1679 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { | 1701 if ((context->regs[REG_MODE_4] & BIT_INTERLACE) && context->framebuf == context->oddbuf) { |
1680 value |= 0x10; | 1702 value |= 0x10; |
1681 } | 1703 } |
1682 uint32_t line= context->vcounter; | 1704 uint32_t line= context->vcounter; |
1683 uint32_t slot = context->hslot; | 1705 uint32_t slot = context->hslot; |
1684 if (line >= (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START) || !(context->regs[REG_MODE_2] & BIT_DISP_EN)) { | 1706 if ( |
1707 ( | |
1708 line >= (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START) | |
1709 && line < 0x1FF | |
1710 ) | |
1711 || !(context->regs[REG_MODE_2] & BIT_DISP_EN) | |
1712 ) { | |
1685 value |= 0x8; | 1713 value |= 0x8; |
1686 } | 1714 } |
1687 if (context->regs[REG_MODE_4] & BIT_H40) { | 1715 if (context->regs[REG_MODE_4] & BIT_H40) { |
1688 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { | 1716 if (slot < HBLANK_END_H40 || slot > HBLANK_START_H40) { |
1689 value |= 0x4; | 1717 value |= 0x4; |
1757 { | 1785 { |
1758 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { | 1786 if (context->regs[REG_MODE_1] & BIT_HVC_LATCH) { |
1759 return context->hv_latch; | 1787 return context->hv_latch; |
1760 } | 1788 } |
1761 uint32_t line= context->vcounter & 0xFF; | 1789 uint32_t line= context->vcounter & 0xFF; |
1762 uint32_t linecyc = (context->hslot * 2) & 0xFF; | 1790 uint32_t linecyc = context->hslot; |
1763 linecyc &= 0xFF; | 1791 linecyc &= 0xFF; |
1764 if (context->double_res) { | 1792 if (context->double_res) { |
1765 line <<= 1; | 1793 line <<= 1; |
1766 if (line & 0x100) { | 1794 if (line & 0x100) { |
1767 line |= 1; | 1795 line |= 1; |
1793 } | 1821 } |
1794 | 1822 |
1795 uint32_t vdp_cycles_next_line(vdp_context * context) | 1823 uint32_t vdp_cycles_next_line(vdp_context * context) |
1796 { | 1824 { |
1797 if (context->regs[REG_MODE_4] & BIT_H40) { | 1825 if (context->regs[REG_MODE_4] & BIT_H40) { |
1798 if (context->hslot < HBLANK_START_H40) { | 1826 if (context->hslot < LINE_CHANGE_H40) { |
1799 return (HBLANK_START_H40 - context->hslot) * MCLKS_SLOT_H40; | 1827 return (HBLANK_START_H40 - context->hslot) * MCLKS_SLOT_H40; |
1800 } else if (context->hslot < 183) { | 1828 } else if (context->hslot < 183) { |
1801 return MCLKS_LINE - (context->hslot - HBLANK_START_H40) * MCLKS_SLOT_H40; | 1829 return MCLKS_LINE - (context->hslot - LINE_CHANGE_H40) * MCLKS_SLOT_H40; |
1802 } else { | 1830 } else { |
1803 return (256-context->hslot + HBLANK_START_H40) * MCLKS_SLOT_H40; | 1831 return (256-context->hslot + LINE_CHANGE_H40) * MCLKS_SLOT_H40; |
1804 } | 1832 } |
1805 } else { | 1833 } else { |
1806 if (context->hslot < HBLANK_START_H32) { | 1834 if (context->hslot < LINE_CHANGE_H32) { |
1807 return (HBLANK_START_H32 - context->hslot) * MCLKS_SLOT_H32; | 1835 return (LINE_CHANGE_H32 - context->hslot) * MCLKS_SLOT_H32; |
1808 } else if (context->hslot < 148) { | 1836 } else if (context->hslot < 148) { |
1809 return MCLKS_LINE - (context->hslot - HBLANK_START_H32) * MCLKS_SLOT_H32; | 1837 return MCLKS_LINE - (context->hslot - LINE_CHANGE_H32) * MCLKS_SLOT_H32; |
1810 } else { | 1838 } else { |
1811 return (256-context->hslot + HBLANK_START_H32) * MCLKS_SLOT_H32; | 1839 return (256-context->hslot + LINE_CHANGE_H32) * MCLKS_SLOT_H32; |
1812 } | 1840 } |
1813 } | 1841 } |
1814 } | 1842 } |
1815 | 1843 |
1816 uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target) | 1844 uint32_t vdp_cycles_to_line(vdp_context * context, uint32_t target) |