comparison blastem.c @ 696:0b2242bbc84a

Added config option to allow specifying a max sync cycle smaller than the end of frame
author Michael Pavone <pavone@retrodev.com>
date Tue, 05 May 2015 08:42:27 -0700
parents e1345921e481
children 7f96bd1cb1be
comparison
equal deleted inserted replaced
695:e1345921e481 696:0b2242bbc84a
31 #define LINES_NTSC 262 31 #define LINES_NTSC 262
32 #define LINES_PAL 312 32 #define LINES_PAL 312
33 33
34 #define MAX_SOUND_CYCLES 100000 34 #define MAX_SOUND_CYCLES 100000
35 35
36 uint32_t mclk_target = 0;
37
38 uint16_t cart[CARTRIDGE_WORDS]; 36 uint16_t cart[CARTRIDGE_WORDS];
39 uint16_t ram[RAM_WORDS]; 37 uint16_t ram[RAM_WORDS];
40 uint8_t z80_ram[Z80_RAM_BYTES]; 38 uint8_t z80_ram[Z80_RAM_BYTES];
41 39
42 int headless = 0; 40 int headless = 0;
125 return 0; 123 return 0;
126 } 124 }
127 125
128 void adjust_int_cycle(m68k_context * context, vdp_context * v_context) 126 void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
129 { 127 {
128 genesis_context *gen = context->system;
129 if (context->sync_cycle - context->current_cycle > gen->max_cycles) {
130 context->sync_cycle = context->current_cycle + gen->max_cycles;
131 }
130 context->int_cycle = CYCLE_NEVER; 132 context->int_cycle = CYCLE_NEVER;
131 if ((context->status & 0x7) < 6) { 133 if ((context->status & 0x7) < 6) {
132 uint32_t next_vint = vdp_next_vint(v_context); 134 uint32_t next_vint = vdp_next_vint(v_context);
133 if (next_vint != CYCLE_NEVER) { 135 if (next_vint != CYCLE_NEVER) {
134 context->int_cycle = next_vint; 136 context->int_cycle = next_vint;
202 } 204 }
203 205
204 uint32_t frame=0; 206 uint32_t frame=0;
205 m68k_context * sync_components(m68k_context * context, uint32_t address) 207 m68k_context * sync_components(m68k_context * context, uint32_t address)
206 { 208 {
207 //TODO: Handle sync targets smaller than a single frame
208 genesis_context * gen = context->system; 209 genesis_context * gen = context->system;
209 vdp_context * v_context = gen->vdp; 210 vdp_context * v_context = gen->vdp;
210 z80_context * z_context = gen->z80; 211 z80_context * z_context = gen->z80;
211 uint32_t mclks = context->current_cycle; 212 uint32_t mclks = context->current_cycle;
212 sync_z80(z_context, mclks); 213 sync_z80(z_context, mclks);
213 sync_sound(gen, mclks); 214 sync_sound(gen, mclks);
214 if (mclks >= mclk_target) { 215 if (mclks >= gen->frame_end) {
215 vdp_run_context(v_context, mclk_target); 216 vdp_run_context(v_context, gen->frame_end);
216 if (vdp_is_frame_over(v_context)) { 217 if (vdp_is_frame_over(v_context)) {
217 //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, mclk_target, v_context->cycles); 218 //printf("reached frame end | MCLK Cycles: %d, Target: %d, VDP cycles: %d\n", mclks, gen->frame_end, v_context->cycles);
218 219
219 if (!headless) { 220 if (!headless) {
220 break_on_sync |= wait_render_frame(v_context, frame_limit); 221 break_on_sync |= wait_render_frame(v_context, frame_limit);
221 } else if(exit_after){ 222 } else if(exit_after){
222 --exit_after; 223 --exit_after;
223 if (!exit_after) { 224 if (!exit_after) {
224 exit(0); 225 exit(0);
225 } 226 }
226 } 227 }
227 frame++; 228 frame++;
228 mclks -= mclk_target; 229 mclks -= gen->frame_end;
229 vdp_adjust_cycles(v_context, mclk_target); 230 vdp_adjust_cycles(v_context, gen->frame_end);
230 io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); 231 io_adjust_cycles(gen->ports, context->current_cycle, gen->frame_end);
231 io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); 232 io_adjust_cycles(gen->ports+1, context->current_cycle, gen->frame_end);
232 io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); 233 io_adjust_cycles(gen->ports+2, context->current_cycle, gen->frame_end);
233 context->current_cycle -= mclk_target; 234 context->current_cycle -= gen->frame_end;
234 z80_adjust_cycles(z_context, mclk_target); 235 z80_adjust_cycles(z_context, gen->frame_end);
235 gen->ym->current_cycle -= mclk_target; 236 gen->ym->current_cycle -= gen->frame_end;
236 gen->psg->cycles -= mclk_target; 237 gen->psg->cycles -= gen->frame_end;
237 if (gen->ym->write_cycle != CYCLE_NEVER) { 238 if (gen->ym->write_cycle != CYCLE_NEVER) {
238 gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; 239 gen->ym->write_cycle = gen->ym->write_cycle >= gen->frame_end ? gen->ym->write_cycle - gen->frame_end : 0;
239 } 240 }
240 if (mclks) { 241 if (mclks) {
241 vdp_run_context(v_context, mclks); 242 vdp_run_context(v_context, mclks);
242 } 243 }
243 mclk_target = vdp_cycles_to_frame_end(v_context); 244 gen->frame_end = vdp_cycles_to_frame_end(v_context);
244 context->sync_cycle = mclk_target;
245 } else { 245 } else {
246 vdp_run_context(v_context, mclks); 246 vdp_run_context(v_context, mclks);
247 mclk_target = vdp_cycles_to_frame_end(v_context); 247 gen->frame_end = vdp_cycles_to_frame_end(v_context);
248 } 248 }
249 context->sync_cycle = gen->frame_end;
249 } else { 250 } else {
250 //printf("running VDP for %d cycles\n", mclks - v_context->cycles); 251 //printf("running VDP for %d cycles\n", mclks - v_context->cycles);
251 vdp_run_context(v_context, mclks); 252 vdp_run_context(v_context, mclks);
252 } 253 }
253 if (context->int_ack) { 254 if (context->int_ack) {
288 int blocked; 289 int blocked;
289 uint32_t before_cycle = v_context->cycles; 290 uint32_t before_cycle = v_context->cycles;
290 if (vdp_port < 4) { 291 if (vdp_port < 4) {
291 while (vdp_data_port_write(v_context, value) < 0) { 292 while (vdp_data_port_write(v_context, value) < 0) {
292 while(v_context->flags & FLAG_DMA_RUN) { 293 while(v_context->flags & FLAG_DMA_RUN) {
293 vdp_run_dma_done(v_context, mclk_target); 294 vdp_run_dma_done(v_context, gen->frame_end);
294 if (v_context->cycles >= mclk_target) { 295 if (v_context->cycles >= gen->frame_end) {
295 context->current_cycle = v_context->cycles; 296 context->current_cycle = v_context->cycles;
296 sync_components(context, 0); 297 sync_components(context, 0);
297 } 298 }
298 } 299 }
299 //context->current_cycle = v_context->cycles; 300 //context->current_cycle = v_context->cycles;
301 } else if(vdp_port < 8) { 302 } else if(vdp_port < 8) {
302 blocked = vdp_control_port_write(v_context, value); 303 blocked = vdp_control_port_write(v_context, value);
303 if (blocked) { 304 if (blocked) {
304 while (blocked) { 305 while (blocked) {
305 while(v_context->flags & FLAG_DMA_RUN) { 306 while(v_context->flags & FLAG_DMA_RUN) {
306 vdp_run_dma_done(v_context, mclk_target); 307 vdp_run_dma_done(v_context, gen->frame_end);
307 if (v_context->cycles >= mclk_target) { 308 if (v_context->cycles >= gen->frame_end) {
308 context->current_cycle = v_context->cycles; 309 context->current_cycle = v_context->cycles;
309 sync_components(context, 0); 310 sync_components(context, 0);
310 } 311 }
311 } 312 }
312 if (blocked < 0) { 313 if (blocked < 0) {
1001 1002
1002 context->video_context = gen->vdp; 1003 context->video_context = gen->vdp;
1003 context->system = gen; 1004 context->system = gen;
1004 //cartridge ROM 1005 //cartridge ROM
1005 context->mem_pointers[0] = cart; 1006 context->mem_pointers[0] = cart;
1006 context->target_cycle = context->sync_cycle = mclk_target; 1007 context->target_cycle = context->sync_cycle = gen->frame_end > gen->max_cycles ? gen->frame_end : gen->max_cycles;
1007 //work RAM 1008 //work RAM
1008 context->mem_pointers[1] = ram; 1009 context->mem_pointers[1] = ram;
1009 //save RAM/map 1010 //save RAM/map
1010 context->mem_pointers[2] = initial_mapped; 1011 context->mem_pointers[2] = initial_mapped;
1011 context->mem_pointers[3] = (uint16_t *)gen->save_ram; 1012 context->mem_pointers[3] = (uint16_t *)gen->save_ram;
1265 genesis_context gen; 1266 genesis_context gen;
1266 memset(&gen, 0, sizeof(gen)); 1267 memset(&gen, 0, sizeof(gen));
1267 gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL; 1268 gen.master_clock = gen.normal_clock = fps == 60 ? MCLKS_NTSC : MCLKS_PAL;
1268 1269
1269 init_vdp_context(&v_context, version_reg & 0x40); 1270 init_vdp_context(&v_context, version_reg & 0x40);
1270 mclk_target = vdp_cycles_to_frame_end(&v_context); 1271 gen.frame_end = vdp_cycles_to_frame_end(&v_context);
1272 char * config_cycles = tern_find_ptr(config, "clocksmax_cycles");
1273 gen.max_cycles = config_cycles ? atoi(config_cycles) : 10000000;
1271 1274
1272 ym2612_context y_context; 1275 ym2612_context y_context;
1273 ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0); 1276 ym_init(&y_context, render_sample_rate(), gen.master_clock, MCLKS_PER_YM, render_audio_buffer(), ym_log ? YM_OPT_WAVE_LOG : 0);
1274 1277
1275 psg_context p_context; 1278 psg_context p_context;