comparison vdp.c @ 922:913a6336ce20

Shift slot number to slot behavior mapping by six slots in H40 mode. This makes the line change slot align with the point at which the display turns on and off at the end of the active display area. Also fixed a regression in which an external slot got accidentally changed into a sprite draw slot
author Michael Pavone <pavone@retrodev.com>
date Thu, 28 Jan 2016 09:10:14 -0800
parents 2be771c4dfbd
children 8e012ece95c1
comparison
equal deleted inserted replaced
921:2be771c4dfbd 922:913a6336ce20
22 22
23 #define MCLKS_SLOT_H40 16 23 #define MCLKS_SLOT_H40 16
24 #define MCLKS_SLOT_H32 20 24 #define MCLKS_SLOT_H32 20
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 4 //old value was 23, but recent tests suggest the actual value is close to the H40 one 26 #define VINT_SLOT_H32 4 //old value was 23, but recent tests suggest the actual value is close to the H40 one
27 #define HSYNC_SLOT_H40 234 27 #define HSYNC_SLOT_H40 228
28 #define HSYNC_END_H40 (HSYNC_SLOT_H40+17) 28 #define HSYNC_END_H40 (HSYNC_SLOT_H40+17)
29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32) 29 #define HSYNC_END_H32 (33 * MCLKS_SLOT_H32)
30 #define HBLANK_START_H40 178 //should be 179 according to Nemesis, but 178 seems to fit slightly better with my test ROM results 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 0 //should be 5.5 according to Nemesis, but 0 seems to fit better with my test ROM results 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 233 //should be 147 according to Nemesis which is very different from my test ROM result 32 #define HBLANK_START_H32 233 //should be 147 according to Nemesis which is very different from my test ROM result
979 979
980 #define COLUMN_RENDER_BLOCK(column, startcyc) \ 980 #define COLUMN_RENDER_BLOCK(column, startcyc) \
981 case startcyc:\ 981 case startcyc:\
982 read_map_scroll_a(column, context->vcounter, context);\ 982 read_map_scroll_a(column, context->vcounter, context);\
983 CHECK_LIMIT\ 983 CHECK_LIMIT\
984 case (startcyc+1):\ 984 case ((startcyc+1)&0xFF):\
985 external_slot(context);\ 985 external_slot(context);\
986 CHECK_LIMIT\ 986 CHECK_LIMIT\
987 case (startcyc+2):\ 987 case ((startcyc+2)&0xFF):\
988 render_map_1(context);\ 988 render_map_1(context);\
989 CHECK_LIMIT\ 989 CHECK_LIMIT\
990 case (startcyc+3):\ 990 case ((startcyc+3)&0xFF):\
991 render_map_2(context);\ 991 render_map_2(context);\
992 CHECK_LIMIT\ 992 CHECK_LIMIT\
993 case (startcyc+4):\ 993 case ((startcyc+4)&0xFF):\
994 read_map_scroll_b(column, context->vcounter, context);\ 994 read_map_scroll_b(column, context->vcounter, context);\
995 CHECK_LIMIT\ 995 CHECK_LIMIT\
996 case (startcyc+5):\ 996 case ((startcyc+5)&0xFF):\
997 read_sprite_x(context->vcounter, context);\ 997 read_sprite_x(context->vcounter, context);\
998 CHECK_LIMIT\ 998 CHECK_LIMIT\
999 case (startcyc+6):\ 999 case ((startcyc+6)&0xFF):\
1000 render_map_3(context);\ 1000 render_map_3(context);\
1001 CHECK_LIMIT\ 1001 CHECK_LIMIT\
1002 case (startcyc+7):\ 1002 case ((startcyc+7)&0xFF):\
1003 render_map_output(context->vcounter, column, context);\ 1003 render_map_output(context->vcounter, column, context);\
1004 CHECK_LIMIT 1004 CHECK_LIMIT
1005 1005
1006 #define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \ 1006 #define COLUMN_RENDER_BLOCK_REFRESH(column, startcyc) \
1007 case startcyc:\ 1007 case startcyc:\
1027 case (startcyc+6):\ 1027 case (startcyc+6):\
1028 render_map_3(context);\ 1028 render_map_3(context);\
1029 CHECK_LIMIT\ 1029 CHECK_LIMIT\
1030 case (startcyc+7):\ 1030 case (startcyc+7):\
1031 render_map_output(context->vcounter, column, context);\ 1031 render_map_output(context->vcounter, column, context);\
1032 if (column == 40 || (column == 32 && startcyc == 124)) {\ 1032 if (column == 32 && startcyc == 124) {\
1033 vdp_advance_line(context);\ 1033 vdp_advance_line(context);\
1034 }\ 1034 }\
1035 CHECK_LIMIT 1035 CHECK_LIMIT
1036 1036
1037 #define SPRITE_RENDER_H40(slot) \ 1037 #define SPRITE_RENDER_H40(slot) \
1039 render_sprite_cells( context);\ 1039 render_sprite_cells( context);\
1040 scan_sprite_table(context->vcounter, context);\ 1040 scan_sprite_table(context->vcounter, context);\
1041 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } \ 1041 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } \
1042 if (slot == 182) {\ 1042 if (slot == 182) {\
1043 context->hslot = 229;\ 1043 context->hslot = 229;\
1044 context->cycles += slot_cycles;\ 1044 context->cycles += h40_hsync_cycles[0];\
1045 } else {\ 1045 } else {\
1046 context->hslot++;\ 1046 context->hslot++;\
1047 if (slot >= HSYNC_SLOT_H40 && slot < HSYNC_END_H40) {\ 1047 if (slot >= HSYNC_SLOT_H40 && slot < HSYNC_END_H40) {\
1048 context->cycles += h40_hsync_cycles[slot - HSYNC_SLOT_H40];\ 1048 context->cycles += h40_hsync_cycles[slot - HSYNC_SLOT_H40];\
1049 } else {\ 1049 } else {\
1073 uint32_t const slot_cycles = MCLKS_SLOT_H40; 1073 uint32_t const slot_cycles = MCLKS_SLOT_H40;
1074 switch(context->hslot) 1074 switch(context->hslot)
1075 { 1075 {
1076 for (;;) 1076 for (;;)
1077 { 1077 {
1078 //sprite attribute table scan starts
1078 case 165: 1079 case 165:
1079 external_slot(context);
1080 CHECK_LIMIT
1081 case 166:
1082 external_slot(context);
1083 CHECK_LIMIT
1084 //sprite render to line buffer starts
1085 case 167:
1086 context->cur_slot = MAX_DRAWS-1;
1087 memset(context->linebuf, 0, LINEBUF_SIZE);
1088 if (context->vcounter == 0x1FF) {
1089 external_slot(context);
1090 } else {
1091 render_sprite_cells(context);
1092 }
1093 CHECK_LIMIT
1094 case 168:
1095 if (context->vcounter == 0x1FF) {
1096 external_slot(context);
1097 } else {
1098 render_sprite_cells(context);
1099 }
1100 CHECK_LIMIT
1101 case 169:
1102 if (context->vcounter == 0x1FF) {
1103 external_slot(context);
1104 } else {
1105 render_sprite_cells(context);
1106 }
1107 CHECK_LIMIT
1108 case 170:
1109 if (context->vcounter == 0x1FF) {
1110 external_slot(context);
1111 } else {
1112 render_sprite_cells(context);
1113 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
1114 context->hslot++;
1115 context->cycles += slot_cycles;
1116 return;
1117 }
1118 }
1119 CHECK_LIMIT
1120 //sprite attribute table scan starts
1121 case 171:
1122 context->sprite_index = 0x80; 1080 context->sprite_index = 0x80;
1123 context->slot_counter = MAX_SPRITES_LINE; 1081 context->slot_counter = MAX_SPRITES_LINE;
1124 render_sprite_cells( context); 1082 render_sprite_cells( context);
1125 scan_sprite_table(context->vcounter, context); 1083 scan_sprite_table(context->vcounter, context);
1126 CHECK_LIMIT 1084 CHECK_LIMIT
1085 SPRITE_RENDER_H40(166)
1086 SPRITE_RENDER_H40(167)
1087 case 168:
1088 external_slot(context);
1089 CHECK_LIMIT
1090 SPRITE_RENDER_H40(169)
1091 SPRITE_RENDER_H40(170)
1092 SPRITE_RENDER_H40(171)
1127 SPRITE_RENDER_H40(172) 1093 SPRITE_RENDER_H40(172)
1128 SPRITE_RENDER_H40(173) 1094 SPRITE_RENDER_H40(173)
1129 SPRITE_RENDER_H40(174) 1095 SPRITE_RENDER_H40(174)
1130 SPRITE_RENDER_H40(175) 1096 SPRITE_RENDER_H40(175)
1131 SPRITE_RENDER_H40(176) 1097 SPRITE_RENDER_H40(176)
1132 SPRITE_RENDER_H40(177) 1098 SPRITE_RENDER_H40(177)
1133 SPRITE_RENDER_H40(178) 1099 SPRITE_RENDER_H40(178)
1134 SPRITE_RENDER_H40(179) 1100 SPRITE_RENDER_H40(179)
1135 SPRITE_RENDER_H40(180) 1101 SPRITE_RENDER_H40(180)
1136 SPRITE_RENDER_H40(181) 1102 SPRITE_RENDER_H40(181)
1103 //!HSYNC asserted
1137 SPRITE_RENDER_H40(182) 1104 SPRITE_RENDER_H40(182)
1138 SPRITE_RENDER_H40(229) 1105 SPRITE_RENDER_H40(229)
1139 SPRITE_RENDER_H40(230) 1106 SPRITE_RENDER_H40(230)
1140 SPRITE_RENDER_H40(231) 1107 SPRITE_RENDER_H40(231)
1141 SPRITE_RENDER_H40(232) 1108 SPRITE_RENDER_H40(232)
1142 SPRITE_RENDER_H40(233) 1109 SPRITE_RENDER_H40(233)
1143 //!HSYNC asserted
1144 SPRITE_RENDER_H40(234) 1110 SPRITE_RENDER_H40(234)
1145 SPRITE_RENDER_H40(235) 1111 SPRITE_RENDER_H40(235)
1146 SPRITE_RENDER_H40(236) 1112 SPRITE_RENDER_H40(236)
1147 SPRITE_RENDER_H40(237) 1113 SPRITE_RENDER_H40(237)
1148 SPRITE_RENDER_H40(238) 1114 SPRITE_RENDER_H40(238)
1149 SPRITE_RENDER_H40(239) 1115 SPRITE_RENDER_H40(239)
1150 SPRITE_RENDER_H40(240) 1116 SPRITE_RENDER_H40(240)
1151 SPRITE_RENDER_H40(241) 1117 SPRITE_RENDER_H40(241)
1152 SPRITE_RENDER_H40(242) 1118 case 242:
1153 SPRITE_RENDER_H40(243)
1154 SPRITE_RENDER_H40(244)
1155 SPRITE_RENDER_H40(245)
1156 SPRITE_RENDER_H40(246)
1157 SPRITE_RENDER_H40(247)
1158 case 248:
1159 address = (context->regs[REG_HSCROLL] & 0x3F) << 10; 1119 address = (context->regs[REG_HSCROLL] & 0x3F) << 10;
1160 mask = 0; 1120 mask = 0;
1161 if (context->regs[REG_MODE_3] & 0x2) { 1121 if (context->regs[REG_MODE_3] & 0x2) {
1162 mask |= 0xF8; 1122 mask |= 0xF8;
1163 } 1123 }
1171 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } 1131 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); }
1172 context->hslot++; 1132 context->hslot++;
1173 context->cycles += h40_hsync_cycles[14]; 1133 context->cycles += h40_hsync_cycles[14];
1174 CHECK_ONLY 1134 CHECK_ONLY
1175 //!HSYNC high 1135 //!HSYNC high
1176 SPRITE_RENDER_H40(249) 1136 SPRITE_RENDER_H40(243)
1177 SPRITE_RENDER_H40(250) 1137 SPRITE_RENDER_H40(244)
1178 SPRITE_RENDER_H40(251) 1138 SPRITE_RENDER_H40(245)
1179 SPRITE_RENDER_H40(252) 1139 SPRITE_RENDER_H40(246)
1180 case 253: 1140 case 247:
1181 read_map_scroll_a(0, context->vcounter, context); 1141 read_map_scroll_a(0, context->vcounter, context);
1182 CHECK_LIMIT 1142 CHECK_LIMIT
1183 SPRITE_RENDER_H40(254) 1143 SPRITE_RENDER_H40(248)
1184 case 255: 1144 case 249:
1185 render_map_1(context); 1145 render_map_1(context);
1186 scan_sprite_table(context->vcounter, context);//Just a guess 1146 scan_sprite_table(context->vcounter, context);//Just a guess
1187 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); } 1147 if (context->flags & FLAG_DMA_RUN) { run_dma_src(context, context->hslot); }
1188 context->hslot = 0; 1148 CHECK_LIMIT
1189 context->cycles += slot_cycles; 1149 case 250:
1190 CHECK_ONLY
1191 case 0:
1192 render_map_2(context); 1150 render_map_2(context);
1193 scan_sprite_table(context->vcounter, context);//Just a guess 1151 scan_sprite_table(context->vcounter, context);//Just a guess
1194 CHECK_LIMIT 1152 CHECK_LIMIT
1195 case 1: 1153 case 251:
1196 read_map_scroll_b(0, context->vcounter, context); 1154 read_map_scroll_b(0, context->vcounter, context);
1197 CHECK_LIMIT 1155 CHECK_LIMIT
1198 SPRITE_RENDER_H40(2) 1156 SPRITE_RENDER_H40(252)
1199 case 3: 1157 case 253:
1200 render_map_3(context); 1158 render_map_3(context);
1201 scan_sprite_table(context->vcounter, context);//Just a guess 1159 scan_sprite_table(context->vcounter, context);//Just a guess
1202 CHECK_LIMIT 1160 CHECK_LIMIT
1203 case 4: 1161 case 254:
1204 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) { 1162 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
1205 context->flags2 |= FLAG2_VINT_PENDING; 1163 context->flags2 |= FLAG2_VINT_PENDING;
1206 context->pending_vint_start = context->cycles; 1164 context->pending_vint_start = context->cycles;
1207 } 1165 }
1208 render_map_output(context->vcounter, 0, context); 1166 render_map_output(context->vcounter, 0, context);
1212 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter; 1170 //context->slot_counter = MAX_SPRITES_LINE - context->slot_counter;
1213 context->cur_slot = MAX_SPRITES_LINE-1; 1171 context->cur_slot = MAX_SPRITES_LINE-1;
1214 context->sprite_draws = MAX_DRAWS; 1172 context->sprite_draws = MAX_DRAWS;
1215 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED); 1173 context->flags &= (~FLAG_CAN_MASK & ~FLAG_MASKED);
1216 CHECK_LIMIT 1174 CHECK_LIMIT
1217 COLUMN_RENDER_BLOCK(2, 5) 1175 COLUMN_RENDER_BLOCK(2, 255)
1218 COLUMN_RENDER_BLOCK(4, 13) 1176 COLUMN_RENDER_BLOCK(4, 7)
1219 COLUMN_RENDER_BLOCK(6, 21) 1177 COLUMN_RENDER_BLOCK(6, 15)
1220 COLUMN_RENDER_BLOCK_REFRESH(8, 29) 1178 COLUMN_RENDER_BLOCK_REFRESH(8, 23)
1221 COLUMN_RENDER_BLOCK(10, 37) 1179 COLUMN_RENDER_BLOCK(10, 31)
1222 COLUMN_RENDER_BLOCK(12, 45) 1180 COLUMN_RENDER_BLOCK(12, 39)
1223 COLUMN_RENDER_BLOCK(14, 53) 1181 COLUMN_RENDER_BLOCK(14, 47)
1224 COLUMN_RENDER_BLOCK_REFRESH(16, 61) 1182 COLUMN_RENDER_BLOCK_REFRESH(16, 55)
1225 COLUMN_RENDER_BLOCK(18, 69) 1183 COLUMN_RENDER_BLOCK(18, 63)
1226 COLUMN_RENDER_BLOCK(20, 77) 1184 COLUMN_RENDER_BLOCK(20, 71)
1227 COLUMN_RENDER_BLOCK(22, 85) 1185 COLUMN_RENDER_BLOCK(22, 79)
1228 COLUMN_RENDER_BLOCK_REFRESH(24, 93) 1186 COLUMN_RENDER_BLOCK_REFRESH(24, 87)
1229 COLUMN_RENDER_BLOCK(26, 101) 1187 COLUMN_RENDER_BLOCK(26, 95)
1230 COLUMN_RENDER_BLOCK(28, 109) 1188 COLUMN_RENDER_BLOCK(28, 103)
1231 COLUMN_RENDER_BLOCK(30, 117) 1189 COLUMN_RENDER_BLOCK(30, 111)
1232 COLUMN_RENDER_BLOCK_REFRESH(32, 125) 1190 COLUMN_RENDER_BLOCK_REFRESH(32, 119)
1233 COLUMN_RENDER_BLOCK(34, 133) 1191 COLUMN_RENDER_BLOCK(34, 127)
1234 COLUMN_RENDER_BLOCK(36, 141) 1192 COLUMN_RENDER_BLOCK(36, 135)
1235 COLUMN_RENDER_BLOCK(38, 149) 1193 COLUMN_RENDER_BLOCK(38, 143)
1236 COLUMN_RENDER_BLOCK_REFRESH(40, 157) 1194 COLUMN_RENDER_BLOCK_REFRESH(40, 151)
1195 case 159:
1196 external_slot(context);
1197 CHECK_LIMIT
1198 case 160:
1199 external_slot(context);
1200 CHECK_LIMIT
1201 //sprite render to line buffer starts
1202 case 161:
1203 context->cur_slot = MAX_DRAWS-1;
1204 memset(context->linebuf, 0, LINEBUF_SIZE);
1205 render_sprite_cells(context);
1206 CHECK_LIMIT
1207 case 162:
1208 render_sprite_cells(context);
1209 CHECK_LIMIT
1210 case 163:
1211 render_sprite_cells(context);
1212 CHECK_LIMIT
1213 case 164:
1214 render_sprite_cells(context);
1215 vdp_advance_line(context);
1216 if (context->vcounter == (context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START)) {
1217 context->hslot++;
1218 context->cycles += slot_cycles;
1219 return;
1220 }
1221 CHECK_LIMIT
1237 } 1222 }
1238 default: 1223 default:
1239 context->hslot++; 1224 context->hslot++;
1240 context->cycles += slot_cycles; 1225 context->cycles += slot_cycles;
1241 return; 1226 return;
1443 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START; 1428 uint32_t inactive_start = context->latched_mode & BIT_PAL ? PAL_INACTIVE_START : NTSC_INACTIVE_START;
1444 //line 0x1FF is basically active even though it's not displayed 1429 //line 0x1FF is basically active even though it's not displayed
1445 uint8_t active_slot = context->vcounter < inactive_start || context->vcounter == 0x1FF; 1430 uint8_t active_slot = context->vcounter < inactive_start || context->vcounter == 0x1FF;
1446 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40; 1431 uint8_t is_h40 = context->regs[REG_MODE_4] & BIT_H40;
1447 if (context->vcounter == inactive_start) { 1432 if (context->vcounter == inactive_start) {
1448 if (is_h40) { 1433 if (!is_h40) {
1449 //the first inactive line behaves as an active one for the first 4 slots
1450 if (context->hslot > LINE_CHANGE_H40 && context->hslot < 171) {
1451 active_slot = 1;
1452 }
1453 } else {
1454 //the first inactive line behaves as an active one for the first few slots 1434 //the first inactive line behaves as an active one for the first few slots
1455 if (context->hslot > LINE_CHANGE_H32 && context->hslot < 138) { 1435 if (context->hslot > LINE_CHANGE_H32 && context->hslot < 138) {
1456 active_slot = 1; 1436 active_slot = 1;
1457 } 1437 }
1458 } 1438 }
1463 } else { 1443 } else {
1464 vdp_h32(context, target_cycles); 1444 vdp_h32(context, target_cycles);
1465 } 1445 }
1466 } else { 1446 } else {
1467 if (is_h40) { 1447 if (is_h40) {
1468 if (context->hslot == 167) { 1448 if (context->hslot == 161) {
1469 context->cur_slot = MAX_DRAWS-1; 1449 context->cur_slot = MAX_DRAWS-1;
1470 memset(context->linebuf, 0, LINEBUF_SIZE); 1450 memset(context->linebuf, 0, LINEBUF_SIZE);
1471 } else if (context->hslot == 171) { 1451 } else if (context->hslot == 165) {
1472 context->sprite_index = 0x80; 1452 context->sprite_index = 0x80;
1473 context->slot_counter = MAX_SPRITES_LINE; 1453 context->slot_counter = MAX_SPRITES_LINE;
1474 } 1454 }
1475 } else { 1455 } else {
1476 if (context->hslot == 134) { 1456 if (context->hslot == 134) {
1488 context->pending_vint_start = context->cycles; 1468 context->pending_vint_start = context->cycles;
1489 } 1469 }
1490 } 1470 }
1491 uint32_t inccycles; 1471 uint32_t inccycles;
1492 if (is_h40) { 1472 if (is_h40) {
1493 if (context->hslot < HSYNC_SLOT_H40 || context->hslot >= HSYNC_END_H40) { 1473 if (context->hslot == 182) {
1474 inccycles = h40_hsync_cycles[0];
1475 } else if (context->hslot < HSYNC_SLOT_H40 || context->hslot >= HSYNC_END_H40) {
1494 inccycles = MCLKS_SLOT_H40; 1476 inccycles = MCLKS_SLOT_H40;
1495 } else { 1477 } else {
1496 inccycles = h40_hsync_cycles[context->hslot-HSYNC_SLOT_H40]; 1478 inccycles = h40_hsync_cycles[context->hslot-HSYNC_SLOT_H40];
1497 } 1479 }
1498 } else { 1480 } else {