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;