Mercurial > repos > blastem
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; |