Mercurial > repos > blastem
comparison vdp.c @ 330:57453d3d8be4
Initial stab at implementing funky clock adjustments during HSYNC for H40 mode
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 13 May 2013 23:42:52 -0700 |
parents | fd5f6577db9b |
children | de17e0352f27 |
comparison
equal
deleted
inserted
replaced
329:fd5f6577db9b | 330:57453d3d8be4 |
---|---|
38 | 38 |
39 #define VINT_SLOTS_H40 (21+16+10) //21 slots before HSYNC, 16 during, 10 after TODO: deal with clock switching during HSYNC | 39 #define VINT_SLOTS_H40 (21+16+10) //21 slots before HSYNC, 16 during, 10 after TODO: deal with clock switching during HSYNC |
40 #define VINT_SLOTS_H32 (33+20+7) //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number | 40 #define VINT_SLOTS_H32 (33+20+7) //33 slots before HSYNC, 20 during, 7 after TODO: confirm final number |
41 #define MCLKS_SLOT_H40 16 | 41 #define MCLKS_SLOT_H40 16 |
42 #define MCLKS_SLOT_H32 20 | 42 #define MCLKS_SLOT_H32 20 |
43 #define HSYNC_SLOT_H40 21 | |
44 #define MCLK_WEIRD_END (HSYNC_SLOT_H40*MCLKS_SLOT_H40 + 332) | |
45 #define SLOT_WEIRD_END (HSYNC_SLOT_H40+17) | |
43 | 46 |
44 void init_vdp_context(vdp_context * context) | 47 void init_vdp_context(vdp_context * context) |
45 { | 48 { |
46 memset(context, 0, sizeof(*context)); | 49 memset(context, 0, sizeof(*context)); |
47 context->vdpmem = malloc(VRAM_SIZE); | 50 context->vdpmem = malloc(VRAM_SIZE); |
1057 void latch_mode(vdp_context * context) | 1060 void latch_mode(vdp_context * context) |
1058 { | 1061 { |
1059 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); | 1062 context->latched_mode = (context->regs[REG_MODE_4] & 0x81) | (context->regs[REG_MODE_2] & BIT_PAL); |
1060 } | 1063 } |
1061 | 1064 |
1062 int is_refresh(vdp_context * context) | 1065 int is_refresh(vdp_context * context, uint32_t slot) |
1063 { | 1066 { |
1064 uint32_t linecyc = context->cycles % MCLKS_LINE; | |
1065 if (context->latched_mode & BIT_H40) { | 1067 if (context->latched_mode & BIT_H40) { |
1066 linecyc = linecyc/16; | |
1067 //TODO: Figure out the exact behavior that reduces DMA slots for direct color DMA demos | 1068 //TODO: Figure out the exact behavior that reduces DMA slots for direct color DMA demos |
1068 return (linecyc == 37 || linecyc == 69 || linecyc == 102 || linecyc == 133 || linecyc == 165 || linecyc == 197 || linecyc >= 210 || (linecyc < 6 && (context->flags & FLAG_DMA_RUN) && ((context->dma_cd & 0xF) == CRAM_WRITE))); | 1069 return (slot == 37 || slot == 69 || slot == 102 || slot == 133 || slot == 165 || slot == 197 || slot >= 210 || (slot < 6 && (context->flags & FLAG_DMA_RUN) && ((context->dma_cd & 0xF) == CRAM_WRITE))); |
1069 } else { | 1070 } else { |
1070 linecyc = linecyc/20; | |
1071 //TODO: Figure out which slots are refresh when display is off in 32-cell mode | 1071 //TODO: Figure out which slots are refresh when display is off in 32-cell mode |
1072 //These numbers are guesses based on H40 numbers | 1072 //These numbers are guesses based on H40 numbers |
1073 return (linecyc == 24 || linecyc == 56 || linecyc == 88 || linecyc == 120 || linecyc == 152 || (linecyc < 5 && (context->flags & FLAG_DMA_RUN) && ((context->dma_cd & 0xF) == CRAM_WRITE))); | 1073 return (slot == 24 || slot == 56 || slot == 88 || slot == 120 || slot == 152 || (slot < 5 && (context->flags & FLAG_DMA_RUN) && ((context->dma_cd & 0xF) == CRAM_WRITE))); |
1074 //The numbers below are the refresh slots during active display | 1074 //The numbers below are the refresh slots during active display |
1075 //return (linecyc == 66 || linecyc == 98 || linecyc == 130 || linecyc == 162); | 1075 //return (slot == 66 || slot == 98 || slot == 130 || slot == 162); |
1076 } | 1076 } |
1077 } | 1077 } |
1078 | 1078 |
1079 void check_render_bg(vdp_context * context, int32_t line) | 1079 void check_render_bg(vdp_context * context, int32_t line, uint32_t slot) |
1080 { | 1080 { |
1081 if (line > 0) { | 1081 if (line > 0) { |
1082 line -= 1; | 1082 line -= 1; |
1083 uint16_t * start = NULL, *end = NULL; | 1083 uint16_t * start = NULL, *end = NULL; |
1084 uint32_t linecyc = (context->cycles % MCLKS_LINE); | |
1085 if (context->latched_mode & BIT_H40) { | 1084 if (context->latched_mode & BIT_H40) { |
1086 linecyc /= 16; | 1085 if (slot >= 50 && slot < 210) { |
1087 if (linecyc >= 50 && linecyc < 210) { | 1086 uint32_t x = (slot-50)*2; |
1088 uint32_t x = (linecyc-50)*2; | |
1089 start = context->framebuf + line * 320 + x; | 1087 start = context->framebuf + line * 320 + x; |
1090 end = start + 2; | 1088 end = start + 2; |
1091 } | 1089 } |
1092 } else { | 1090 } else { |
1093 linecyc /= 20; | 1091 if (slot >= 43 && slot < 171) { |
1094 if (linecyc >= 43 && linecyc < 171) { | 1092 uint32_t x = (slot-43)*2; |
1095 uint32_t x = (linecyc-43)*2; | |
1096 start = context->framebuf + line * 320 + x; | 1093 start = context->framebuf + line * 320 + x; |
1097 end = start + 2; | 1094 end = start + 2; |
1098 } | 1095 } |
1099 } | 1096 } |
1100 uint16_t color = (context->cram[context->regs[REG_BG_COLOR] & 0x3F] & 0xEEE); | 1097 uint16_t color = (context->cram[context->regs[REG_BG_COLOR] & 0x3F] & 0xEEE); |
1128 uint32_t intcyc = context->latched_mode & BIT_H40 ? VINT_SLOTS_H40 * MCLKS_SLOT_H40 : VINT_SLOTS_H32 * MCLKS_SLOT_H32; | 1125 uint32_t intcyc = context->latched_mode & BIT_H40 ? VINT_SLOTS_H40 * MCLKS_SLOT_H40 : VINT_SLOTS_H32 * MCLKS_SLOT_H32; |
1129 if (linecyc == intcyc) { | 1126 if (linecyc == intcyc) { |
1130 context->flags2 |= FLAG2_VINT_PENDING; | 1127 context->flags2 |= FLAG2_VINT_PENDING; |
1131 } | 1128 } |
1132 } | 1129 } |
1130 uint32_t inccycles, slot; | |
1131 if (context->latched_mode & BIT_H40){ | |
1132 if (linecyc < MCLKS_SLOT_H40*HSYNC_SLOT_H40) { | |
1133 slot = linecyc/MCLKS_SLOT_H40; | |
1134 inccycles = MCLKS_SLOT_H40; | |
1135 } else if(linecyc < MCLK_WEIRD_END) { | |
1136 switch(linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40)) | |
1137 { | |
1138 case 0: | |
1139 inccycles = 19; | |
1140 slot = 0; | |
1141 break; | |
1142 case 19: | |
1143 slot = 1; | |
1144 inccycles = 20; | |
1145 break; | |
1146 case 39: | |
1147 slot = 2; | |
1148 inccycles = 20; | |
1149 break; | |
1150 case 59: | |
1151 slot = 2; | |
1152 inccycles = 20; | |
1153 break; | |
1154 case 79: | |
1155 slot = 3; | |
1156 inccycles = 18; | |
1157 break; | |
1158 case 97: | |
1159 slot = 4; | |
1160 inccycles = 20; | |
1161 break; | |
1162 case 117: | |
1163 slot = 5; | |
1164 inccycles = 20; | |
1165 break; | |
1166 case 137: | |
1167 slot = 6; | |
1168 inccycles = 20; | |
1169 break; | |
1170 case 157: | |
1171 slot = 7; | |
1172 inccycles = 18; | |
1173 break; | |
1174 case 175: | |
1175 slot = 8; | |
1176 inccycles = 20; | |
1177 break; | |
1178 case 195: | |
1179 slot = 9; | |
1180 inccycles = 20; | |
1181 break; | |
1182 case 215: | |
1183 slot = 11; | |
1184 inccycles = 20; | |
1185 break; | |
1186 case 235: | |
1187 slot = 12; | |
1188 inccycles = 18; | |
1189 break; | |
1190 case 253: | |
1191 slot = 13; | |
1192 inccycles = 20; | |
1193 break; | |
1194 case 273: | |
1195 slot = 14; | |
1196 inccycles = 20; | |
1197 break; | |
1198 case 293: | |
1199 slot = 15; | |
1200 inccycles = 20; | |
1201 break; | |
1202 case 313: | |
1203 slot = 16; | |
1204 inccycles = 19; | |
1205 break; | |
1206 default: | |
1207 fprintf(stderr, "cycles after weirdness %d\n", linecyc-(MCLKS_SLOT_H40*HSYNC_SLOT_H40)); | |
1208 exit(1); | |
1209 } | |
1210 slot += HSYNC_SLOT_H40; | |
1211 } else { | |
1212 slot = (linecyc-MCLK_WEIRD_END)/MCLKS_SLOT_H40 + SLOT_WEIRD_END; | |
1213 inccycles = MCLKS_SLOT_H40; | |
1214 } | |
1215 } else { | |
1216 inccycles = MCLKS_SLOT_H32; | |
1217 slot = linecyc/MCLKS_SLOT_H32; | |
1218 } | |
1133 if ((line < active_lines || (line == active_lines && linecyc < (context->latched_mode & BIT_H40 ? 64 : 80))) && context->regs[REG_MODE_2] & DISPLAY_ENABLE) { | 1219 if ((line < active_lines || (line == active_lines && linecyc < (context->latched_mode & BIT_H40 ? 64 : 80))) && context->regs[REG_MODE_2] & DISPLAY_ENABLE) { |
1134 //first sort-of active line is treated as 255 internally | 1220 //first sort-of active line is treated as 255 internally |
1135 //it's used for gathering sprite info for line | 1221 //it's used for gathering sprite info for line |
1136 line = (line - 1) & 0xFF; | 1222 line = (line - 1) & 0xFF; |
1137 | 1223 |
1138 //Convert to slot number | 1224 //Convert to slot number |
1139 if (context->latched_mode & BIT_H40){ | 1225 if (context->latched_mode & BIT_H40){ |
1140 //TODO: Deal with nasty clock switching during HBLANK | 1226 vdp_h40(line, slot, context); |
1141 uint32_t clock_inc = MCLKS_LINE-linecyc < MCLKS_SLOT_H40 ? MCLKS_LINE-linecyc : MCLKS_SLOT_H40; | |
1142 linecyc = linecyc/MCLKS_SLOT_H40; | |
1143 vdp_h40(line, linecyc, context); | |
1144 context->cycles += clock_inc; | |
1145 } else { | 1227 } else { |
1146 linecyc = linecyc/MCLKS_SLOT_H32; | 1228 vdp_h32(line, slot, context); |
1147 vdp_h32(line, linecyc, context); | 1229 } |
1148 context->cycles += MCLKS_SLOT_H32; | 1230 } else { |
1149 } | 1231 if (!is_refresh(context, slot)) { |
1150 } else { | |
1151 if (!is_refresh(context)) { | |
1152 external_slot(context); | 1232 external_slot(context); |
1153 } | 1233 } |
1154 if (line < active_lines) { | 1234 if (line < active_lines) { |
1155 check_render_bg(context, line); | 1235 check_render_bg(context, line, slot); |
1156 } | 1236 } |
1157 if (context->latched_mode & BIT_H40){ | 1237 } |
1158 uint32_t clock_inc = MCLKS_LINE-linecyc < MCLKS_SLOT_H40 ? MCLKS_LINE-linecyc : MCLKS_SLOT_H40; | 1238 context->cycles += inccycles; |
1159 //TODO: Deal with nasty clock switching during HBLANK | |
1160 context->cycles += clock_inc; | |
1161 } else { | |
1162 context->cycles += MCLKS_SLOT_H32; | |
1163 } | |
1164 } | |
1165 } | 1239 } |
1166 } | 1240 } |
1167 | 1241 |
1168 uint32_t vdp_run_to_vblank(vdp_context * context) | 1242 uint32_t vdp_run_to_vblank(vdp_context * context) |
1169 { | 1243 { |
1338 return value; | 1412 return value; |
1339 } | 1413 } |
1340 | 1414 |
1341 uint16_t vdp_hv_counter_read(vdp_context * context) | 1415 uint16_t vdp_hv_counter_read(vdp_context * context) |
1342 { | 1416 { |
1417 //TODO: deal with clock adjustemnts handled in vdp_run_context | |
1343 uint32_t line= context->cycles / MCLKS_LINE; | 1418 uint32_t line= context->cycles / MCLKS_LINE; |
1344 if (!line) { | 1419 if (!line) { |
1345 line = 0xFF; | 1420 line = 0xFF; |
1346 } else { | 1421 } else { |
1347 line--; | 1422 line--; |
1408 return hcycle; | 1483 return hcycle; |
1409 } | 1484 } |
1410 | 1485 |
1411 uint32_t vdp_next_vint(vdp_context * context) | 1486 uint32_t vdp_next_vint(vdp_context * context) |
1412 { | 1487 { |
1488 //TODO: deal with clock adjustemnts handled in vdp_run_context | |
1413 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { | 1489 if (!(context->regs[REG_MODE_2] & BIT_VINT_EN)) { |
1414 return 0xFFFFFFFF; | 1490 return 0xFFFFFFFF; |
1415 } | 1491 } |
1416 if (context->flags2 & FLAG2_VINT_PENDING) { | 1492 if (context->flags2 & FLAG2_VINT_PENDING) { |
1417 return context->cycles; | 1493 return context->cycles; |