Mercurial > repos > blastem
comparison blastem.c @ 667:30ccf56842d6
All cycle counters are now based off the master clock. This seems to have messed up Z80 interrupt timing (music in Sonic 2 is too slow for instance), but things are generally working
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 03 Jan 2015 16:08:23 -0800 |
parents | 01c51f397db2 |
children | 5439ae7946ca |
comparison
equal
deleted
inserted
replaced
666:b68039895627 | 667:30ccf56842d6 |
---|---|
123 } | 123 } |
124 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area | 124 //TODO: Figure out what happens when you try to DMA from weird adresses like IO or banked Z80 area |
125 return 0; | 125 return 0; |
126 } | 126 } |
127 | 127 |
128 //TODO: Make these dependent on the video mode | |
129 //#define VINT_CYCLE ((MCLKS_LINE * 225 + (148 + 40) * 4)/MCLKS_PER_68K) | |
130 #define ZVINT_CYCLE ((MCLKS_LINE * 225 + (148 + 40) * 4)/MCLKS_PER_Z80) | |
131 //#define VINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_68K) | |
132 //#define ZVINT_CYCLE ((MCLKS_LINE * 226)/MCLKS_PER_Z80) | |
133 | |
134 void adjust_int_cycle(m68k_context * context, vdp_context * v_context) | 128 void adjust_int_cycle(m68k_context * context, vdp_context * v_context) |
135 { | 129 { |
136 context->int_cycle = CYCLE_NEVER; | 130 context->int_cycle = CYCLE_NEVER; |
137 if ((context->status & 0x7) < 6) { | 131 if ((context->status & 0x7) < 6) { |
138 uint32_t next_vint = vdp_next_vint(v_context); | 132 uint32_t next_vint = vdp_next_vint(v_context); |
139 if (next_vint != CYCLE_NEVER) { | 133 if (next_vint != CYCLE_NEVER) { |
140 next_vint /= MCLKS_PER_68K; | |
141 context->int_cycle = next_vint; | 134 context->int_cycle = next_vint; |
142 context->int_num = 6; | 135 context->int_num = 6; |
143 } | 136 } |
144 if ((context->status & 0x7) < 4) { | 137 if ((context->status & 0x7) < 4) { |
145 uint32_t next_hint = vdp_next_hint(v_context); | 138 uint32_t next_hint = vdp_next_hint(v_context); |
146 if (next_hint != CYCLE_NEVER) { | 139 if (next_hint != CYCLE_NEVER) { |
147 next_hint /= MCLKS_PER_68K; | |
148 if (next_hint < context->int_cycle) { | 140 if (next_hint < context->int_cycle) { |
149 context->int_cycle = next_hint; | 141 context->int_cycle = next_hint; |
150 context->int_num = 4; | 142 context->int_num = 4; |
151 | 143 |
152 } | 144 } |
183 void sync_z80(z80_context * z_context, uint32_t mclks) | 175 void sync_z80(z80_context * z_context, uint32_t mclks) |
184 { | 176 { |
185 #ifndef NO_Z80 | 177 #ifndef NO_Z80 |
186 if (z80_enabled && !reset && !busreq) { | 178 if (z80_enabled && !reset && !busreq) { |
187 genesis_context * gen = z_context->system; | 179 genesis_context * gen = z_context->system; |
188 z_context->sync_cycle = mclks / MCLKS_PER_Z80; | 180 z_context->sync_cycle = mclks; |
189 if (z_context->current_cycle < z_context->sync_cycle) { | 181 if (z_context->current_cycle < z_context->sync_cycle) { |
190 if (need_reset) { | 182 if (need_reset) { |
191 z80_reset(z_context); | 183 z80_reset(z_context); |
192 need_reset = 0; | 184 need_reset = 0; |
193 } | 185 } |
194 | 186 |
195 while (z_context->current_cycle < z_context->sync_cycle) { | 187 while (z_context->current_cycle < z_context->sync_cycle) { |
196 if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { | 188 if (z_context->int_pulse_end < z_context->current_cycle || z_context->int_pulse_end == CYCLE_NEVER) { |
197 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp) / MCLKS_PER_Z80; | 189 z_context->int_pulse_start = vdp_next_vint_z80(gen->vdp); |
198 z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; | 190 z_context->int_pulse_end = z_context->int_pulse_start + Z80_VINT_DURATION; |
199 } | 191 } |
200 if (z_context->iff1) { | 192 if (z_context->iff1) { |
201 z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start; | 193 z_context->int_cycle = z_context->int_pulse_start < z_context->int_enable_cycle ? z_context->int_enable_cycle : z_context->int_pulse_start; |
202 } else { | 194 } else { |
209 } | 201 } |
210 } | 202 } |
211 } else | 203 } else |
212 #endif | 204 #endif |
213 { | 205 { |
214 z_context->current_cycle = mclks / MCLKS_PER_Z80; | 206 z_context->current_cycle = mclks; |
215 } | 207 } |
216 } | 208 } |
217 | 209 |
218 void sync_sound(genesis_context * gen, uint32_t target) | 210 void sync_sound(genesis_context * gen, uint32_t target) |
219 { | 211 { |
236 { | 228 { |
237 //TODO: Handle sync targets smaller than a single frame | 229 //TODO: Handle sync targets smaller than a single frame |
238 genesis_context * gen = context->system; | 230 genesis_context * gen = context->system; |
239 vdp_context * v_context = gen->vdp; | 231 vdp_context * v_context = gen->vdp; |
240 z80_context * z_context = gen->z80; | 232 z80_context * z_context = gen->z80; |
241 uint32_t mclks = context->current_cycle * MCLKS_PER_68K; | 233 uint32_t mclks = context->current_cycle; |
242 sync_z80(z_context, mclks); | 234 sync_z80(z_context, mclks); |
243 if (mclks >= mclk_target) { | 235 if (mclks >= mclk_target) { |
244 sync_sound(gen, mclks); | 236 sync_sound(gen, mclks); |
245 gen->ym->current_cycle -= mclk_target; | 237 gen->ym->current_cycle -= mclk_target; |
246 gen->psg->cycles -= mclk_target; | 238 gen->psg->cycles -= mclk_target; |
247 if (gen->ym->write_cycle != CYCLE_NEVER) { | 239 if (gen->ym->write_cycle != CYCLE_NEVER) { |
248 gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target/MCLKS_PER_68K ? gen->ym->write_cycle - mclk_target/MCLKS_PER_68K : 0; | 240 gen->ym->write_cycle = gen->ym->write_cycle >= mclk_target ? gen->ym->write_cycle - mclk_target : 0; |
249 } | 241 } |
250 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); | 242 //printf("reached frame end | 68K Cycles: %d, MCLK Cycles: %d\n", context->current_cycle, mclks); |
251 vdp_run_context(v_context, mclk_target); | 243 vdp_run_context(v_context, mclk_target); |
252 | 244 |
253 if (!headless) { | 245 if (!headless) { |
259 } | 251 } |
260 } | 252 } |
261 frame++; | 253 frame++; |
262 mclks -= mclk_target; | 254 mclks -= mclk_target; |
263 vdp_adjust_cycles(v_context, mclk_target); | 255 vdp_adjust_cycles(v_context, mclk_target); |
264 io_adjust_cycles(gen->ports, context->current_cycle, mclk_target/MCLKS_PER_68K); | 256 io_adjust_cycles(gen->ports, context->current_cycle, mclk_target); |
265 io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target/MCLKS_PER_68K); | 257 io_adjust_cycles(gen->ports+1, context->current_cycle, mclk_target); |
266 io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target/MCLKS_PER_68K); | 258 io_adjust_cycles(gen->ports+2, context->current_cycle, mclk_target); |
267 if (busack_cycle != CYCLE_NEVER) { | 259 if (busack_cycle != CYCLE_NEVER) { |
268 if (busack_cycle > mclk_target/MCLKS_PER_68K) { | 260 if (busack_cycle > mclk_target) { |
269 busack_cycle -= mclk_target/MCLKS_PER_68K; | 261 busack_cycle -= mclk_target; |
270 } else { | 262 } else { |
271 busack_cycle = CYCLE_NEVER; | 263 busack_cycle = CYCLE_NEVER; |
272 busack = new_busack; | 264 busack = new_busack; |
273 } | 265 } |
274 } | 266 } |
275 context->current_cycle -= mclk_target/MCLKS_PER_68K; | 267 context->current_cycle -= mclk_target; |
276 if (z_context->current_cycle >= mclk_target/MCLKS_PER_Z80) { | 268 if (z_context->current_cycle >= mclk_target) { |
277 z_context->current_cycle -= mclk_target/MCLKS_PER_Z80; | 269 z_context->current_cycle -= mclk_target; |
278 } else { | 270 } else { |
279 z_context->current_cycle = 0; | 271 z_context->current_cycle = 0; |
280 } | 272 } |
281 if (z_context->int_cycle != CYCLE_NEVER) { | 273 if (z_context->int_cycle != CYCLE_NEVER) { |
282 if (z_context->int_cycle >= mclk_target/MCLKS_PER_Z80) { | 274 if (z_context->int_cycle >= mclk_target) { |
283 z_context->int_cycle -= mclk_target/MCLKS_PER_Z80; | 275 z_context->int_cycle -= mclk_target; |
284 } else { | 276 } else { |
285 z_context->int_cycle = 0; | 277 z_context->int_cycle = 0; |
286 } | 278 } |
287 } | 279 } |
288 if (z_context->int_pulse_start != CYCLE_NEVER) { | 280 if (z_context->int_pulse_start != CYCLE_NEVER) { |
289 if (z_context->int_pulse_end >= mclk_target/MCLKS_PER_Z80) { | 281 if (z_context->int_pulse_end >= mclk_target) { |
290 z_context->int_pulse_end -= mclk_target/MCLKS_PER_Z80; | 282 z_context->int_pulse_end -= mclk_target; |
291 if (z_context->int_pulse_start >= mclk_target/MCLKS_PER_Z80) { | 283 if (z_context->int_pulse_start >= mclk_target) { |
292 z_context->int_pulse_start -= mclk_target/MCLKS_PER_Z80; | 284 z_context->int_pulse_start -= mclk_target; |
293 } else { | 285 } else { |
294 z_context->int_pulse_start = 0; | 286 z_context->int_pulse_start = 0; |
295 } | 287 } |
296 } | 288 } |
297 } else { | 289 } else { |
298 z_context->int_pulse_start = CYCLE_NEVER; | 290 z_context->int_pulse_start = CYCLE_NEVER; |
299 z_context->int_pulse_end = CYCLE_NEVER; | 291 z_context->int_pulse_end = CYCLE_NEVER; |
300 } | 292 } |
301 if (z_context->int_enable_cycle >= mclk_target/MCLKS_PER_Z80) { | 293 if (z_context->int_enable_cycle >= mclk_target) { |
302 z_context->int_enable_cycle -= mclk_target/MCLKS_PER_Z80; | 294 z_context->int_enable_cycle -= mclk_target; |
303 } else { | 295 } else { |
304 z_context->int_enable_cycle = 0; | 296 z_context->int_enable_cycle = 0; |
305 } | 297 } |
306 if (mclks) { | 298 if (mclks) { |
307 vdp_run_context(v_context, mclks); | 299 vdp_run_context(v_context, mclks); |
308 } | 300 } |
309 mclk_target = vdp_cycles_to_frame_end(v_context); | 301 mclk_target = vdp_cycles_to_frame_end(v_context); |
310 context->sync_cycle = mclk_target/MCLKS_PER_68K; | 302 context->sync_cycle = mclk_target; |
311 } else { | 303 } else { |
312 //printf("running VDP for %d cycles\n", mclks - v_context->cycles); | 304 //printf("running VDP for %d cycles\n", mclks - v_context->cycles); |
313 vdp_run_context(v_context, mclks); | 305 vdp_run_context(v_context, mclks); |
314 sync_sound(gen, mclks); | 306 sync_sound(gen, mclks); |
315 } | 307 } |
323 break_on_sync = 0; | 315 break_on_sync = 0; |
324 debugger(context, address); | 316 debugger(context, address); |
325 } | 317 } |
326 if (save_state) { | 318 if (save_state) { |
327 save_state = 0; | 319 save_state = 0; |
320 //advance Z80 core to the start of an instruction | |
328 while (!z_context->pc) | 321 while (!z_context->pc) |
329 { | 322 { |
330 sync_z80(z_context, z_context->current_cycle * MCLKS_PER_Z80 + MCLKS_PER_Z80); | 323 sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80); |
331 } | 324 } |
332 save_gst(gen, "savestate.gst", address); | 325 save_gst(gen, "savestate.gst", address); |
333 } | 326 } |
334 } | 327 } |
335 return context; | 328 return context; |
353 gen->bus_busy = 1; | 346 gen->bus_busy = 1; |
354 while (vdp_data_port_write(v_context, value) < 0) { | 347 while (vdp_data_port_write(v_context, value) < 0) { |
355 while(v_context->flags & FLAG_DMA_RUN) { | 348 while(v_context->flags & FLAG_DMA_RUN) { |
356 vdp_run_dma_done(v_context, mclk_target); | 349 vdp_run_dma_done(v_context, mclk_target); |
357 if (v_context->cycles >= mclk_target) { | 350 if (v_context->cycles >= mclk_target) { |
358 context->current_cycle = v_context->cycles / MCLKS_PER_68K; | 351 context->current_cycle = v_context->cycles; |
359 if (context->current_cycle * MCLKS_PER_68K < mclk_target) { | 352 if (context->current_cycle < mclk_target) { |
360 ++context->current_cycle; | 353 context->current_cycle += MCLKS_PER_68K; |
361 } | 354 } |
362 sync_components(context, 0); | 355 sync_components(context, 0); |
363 } | 356 } |
364 } | 357 } |
365 //context->current_cycle = v_context->cycles / MCLKS_PER_68K; | 358 //context->current_cycle = v_context->cycles; |
366 } | 359 } |
367 } else if(vdp_port < 8) { | 360 } else if(vdp_port < 8) { |
368 gen->bus_busy = 1; | 361 gen->bus_busy = 1; |
369 blocked = vdp_control_port_write(v_context, value); | 362 blocked = vdp_control_port_write(v_context, value); |
370 if (blocked) { | 363 if (blocked) { |
371 while (blocked) { | 364 while (blocked) { |
372 while(v_context->flags & FLAG_DMA_RUN) { | 365 while(v_context->flags & FLAG_DMA_RUN) { |
373 vdp_run_dma_done(v_context, mclk_target); | 366 vdp_run_dma_done(v_context, mclk_target); |
374 if (v_context->cycles >= mclk_target) { | 367 if (v_context->cycles >= mclk_target) { |
375 context->current_cycle = v_context->cycles / MCLKS_PER_68K; | 368 context->current_cycle = v_context->cycles; |
376 if (context->current_cycle * MCLKS_PER_68K < mclk_target) { | 369 if (context->current_cycle < mclk_target) { |
377 ++context->current_cycle; | 370 context->current_cycle += MCLKS_PER_68K; |
378 } | 371 } |
379 sync_components(context, 0); | 372 sync_components(context, 0); |
380 } | 373 } |
381 } | 374 } |
382 if (blocked < 0) { | 375 if (blocked < 0) { |
391 } else { | 384 } else { |
392 printf("Illegal write to HV Counter port %X\n", vdp_port); | 385 printf("Illegal write to HV Counter port %X\n", vdp_port); |
393 exit(1); | 386 exit(1); |
394 } | 387 } |
395 if (v_context->cycles != before_cycle) { | 388 if (v_context->cycles != before_cycle) { |
396 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); | 389 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for write\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); |
397 context->current_cycle = v_context->cycles / MCLKS_PER_68K; | 390 context->current_cycle = v_context->cycles; |
398 } | 391 } |
399 } else if (vdp_port < 0x18) { | 392 } else if (vdp_port < 0x18) { |
400 sync_sound(gen, context->current_cycle * MCLKS_PER_68K); | 393 sync_sound(gen, context->current_cycle); |
401 psg_write(gen->psg, value); | 394 psg_write(gen->psg, value); |
402 } else { | 395 } else { |
403 //TODO: Implement undocumented test register(s) | 396 //TODO: Implement undocumented test register(s) |
404 } | 397 } |
405 if (gen->bus_busy) | 398 if (gen->bus_busy) |
425 printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); | 418 printf("machine freeze due to write to Z80 address %X\n", 0x7F00 | vdp_port); |
426 exit(1); | 419 exit(1); |
427 } | 420 } |
428 if (vdp_port < 0x10) { | 421 if (vdp_port < 0x10) { |
429 //These probably won't currently interact well with the 68K accessing the VDP | 422 //These probably won't currently interact well with the 68K accessing the VDP |
430 vdp_run_context(gen->vdp, context->current_cycle * MCLKS_PER_Z80); | 423 vdp_run_context(gen->vdp, context->current_cycle); |
431 if (vdp_port < 4) { | 424 if (vdp_port < 4) { |
432 vdp_data_port_write(gen->vdp, value << 8 | value); | 425 vdp_data_port_write(gen->vdp, value << 8 | value); |
433 } else if (vdp_port < 8) { | 426 } else if (vdp_port < 8) { |
434 vdp_control_port_write(gen->vdp, value << 8 | value); | 427 vdp_control_port_write(gen->vdp, value << 8 | value); |
435 } else { | 428 } else { |
436 printf("Illegal write to HV Counter port %X\n", vdp_port); | 429 printf("Illegal write to HV Counter port %X\n", vdp_port); |
437 exit(1); | 430 exit(1); |
438 } | 431 } |
439 } else if (vdp_port < 0x18) { | 432 } else if (vdp_port < 0x18) { |
440 sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); | 433 sync_sound(gen, context->current_cycle); |
441 psg_write(gen->psg, value); | 434 psg_write(gen->psg, value); |
442 } else { | 435 } else { |
443 vdp_test_port_write(gen->vdp, value); | 436 vdp_test_port_write(gen->vdp, value); |
444 } | 437 } |
445 return context; | 438 return context; |
470 exit(1); | 463 exit(1); |
471 } else { | 464 } else { |
472 value = vdp_test_port_read(v_context); | 465 value = vdp_test_port_read(v_context); |
473 } | 466 } |
474 if (v_context->cycles != before_cycle) { | 467 if (v_context->cycles != before_cycle) { |
475 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles / MCLKS_PER_68K - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); | 468 //printf("68K paused for %d (%d) cycles at cycle %d (%d) for read\n", v_context->cycles - context->current_cycle, v_context->cycles - before_cycle, context->current_cycle, before_cycle); |
476 context->current_cycle = v_context->cycles / MCLKS_PER_68K; | 469 context->current_cycle = v_context->cycles; |
477 } | 470 } |
478 return value; | 471 return value; |
479 } | 472 } |
480 | 473 |
481 uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) | 474 uint8_t vdp_port_read_b(uint32_t vdp_port, m68k_context * context) |
498 genesis_context * gen = context->system; | 491 genesis_context * gen = context->system; |
499 vdp_port &= 0x1F; | 492 vdp_port &= 0x1F; |
500 uint16_t ret; | 493 uint16_t ret; |
501 if (vdp_port < 0x10) { | 494 if (vdp_port < 0x10) { |
502 //These probably won't currently interact well with the 68K accessing the VDP | 495 //These probably won't currently interact well with the 68K accessing the VDP |
503 vdp_run_context(gen->vdp, context->current_cycle * MCLKS_PER_Z80); | 496 vdp_run_context(gen->vdp, context->current_cycle); |
504 if (vdp_port < 4) { | 497 if (vdp_port < 4) { |
505 ret = vdp_data_port_read(gen->vdp); | 498 ret = vdp_data_port_read(gen->vdp); |
506 } else if (vdp_port < 8) { | 499 } else if (vdp_port < 8) { |
507 ret = vdp_control_port_read(gen->vdp); | 500 ret = vdp_control_port_read(gen->vdp); |
508 } else { | 501 } else { |
537 z80_ram[location & 0x1FFF] = value; | 530 z80_ram[location & 0x1FFF] = value; |
538 #ifndef NO_Z80 | 531 #ifndef NO_Z80 |
539 z80_handle_code_write(location & 0x1FFF, gen->z80); | 532 z80_handle_code_write(location & 0x1FFF, gen->z80); |
540 #endif | 533 #endif |
541 } else if (location < 0x6000) { | 534 } else if (location < 0x6000) { |
542 sync_sound(gen, context->current_cycle * MCLKS_PER_68K); | 535 sync_sound(gen, context->current_cycle); |
543 if (location & 1) { | 536 if (location & 1) { |
544 ym_data_write(gen->ym, value); | 537 ym_data_write(gen->ym, value); |
545 } else if(location & 2) { | 538 } else if(location & 2) { |
546 ym_address_write_part2(gen->ym, value); | 539 ym_address_write_part2(gen->ym, value); |
547 } else { | 540 } else { |
591 } | 584 } |
592 if (value & 1) { | 585 if (value & 1) { |
593 dputs("bus requesting Z80"); | 586 dputs("bus requesting Z80"); |
594 | 587 |
595 if(!reset && !busreq) { | 588 if(!reset && !busreq) { |
596 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K + Z80_ACK_DELAY*MCLKS_PER_Z80); | 589 sync_z80(gen->z80, context->current_cycle + Z80_ACK_DELAY*MCLKS_PER_Z80); |
597 busack_cycle = (gen->z80->current_cycle * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; | 590 busack_cycle = gen->z80->current_cycle;//context->current_cycle + Z80_ACK_DELAY; |
598 new_busack = Z80_REQ_ACK; | 591 new_busack = Z80_REQ_ACK; |
599 } | 592 } |
600 busreq = 1; | 593 busreq = 1; |
601 } else { | 594 } else { |
602 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 595 sync_z80(gen->z80, context->current_cycle); |
603 if (busreq) { | 596 if (busreq) { |
604 dputs("releasing z80 bus"); | 597 dputs("releasing z80 bus"); |
605 #ifdef DO_DEBUG_PRINT | 598 #ifdef DO_DEBUG_PRINT |
606 char fname[20]; | 599 char fname[20]; |
607 sprintf(fname, "zram-%d", zram_counter++); | 600 sprintf(fname, "zram-%d", zram_counter++); |
608 FILE * f = fopen(fname, "wb"); | 601 FILE * f = fopen(fname, "wb"); |
609 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 602 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
610 fclose(f); | 603 fclose(f); |
611 #endif | 604 #endif |
612 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; | 605 busack_cycle = gen->z80->current_cycle + Z80_BUSY_DELAY; |
613 new_busack = Z80_REQ_BUSY; | 606 new_busack = Z80_REQ_BUSY; |
614 busreq = 0; | 607 busreq = 0; |
615 } | 608 } |
616 //busack_cycle = CYCLE_NEVER; | 609 //busack_cycle = CYCLE_NEVER; |
617 //busack = Z80_REQ_BUSY; | 610 //busack = Z80_REQ_BUSY; |
618 | 611 |
619 } | 612 } |
620 } else if (location == 0x1200) { | 613 } else if (location == 0x1200) { |
621 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 614 sync_z80(gen->z80, context->current_cycle); |
622 if (value & 1) { | 615 if (value & 1) { |
623 if (reset && busreq) { | 616 if (reset && busreq) { |
624 new_busack = 0; | 617 new_busack = 0; |
625 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; | 618 busack_cycle = gen->z80->current_cycle + Z80_ACK_DELAY;//context->current_cycle + Z80_ACK_DELAY; |
626 } | 619 } |
627 //TODO: Deal with the scenario in which reset is not asserted long enough | 620 //TODO: Deal with the scenario in which reset is not asserted long enough |
628 if (reset) { | 621 if (reset) { |
629 need_reset = 1; | 622 need_reset = 1; |
630 //TODO: Add necessary delay between release of reset and start of execution | 623 //TODO: Add necessary delay between release of reset and start of execution |
631 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80 + 16; | 624 gen->z80->current_cycle = context->current_cycle + 16 * MCLKS_PER_Z80; |
632 } | 625 } |
633 reset = 0; | 626 reset = 0; |
634 } else { | 627 } else { |
635 reset = 1; | 628 reset = 1; |
636 } | 629 } |
667 if (!(busack==Z80_REQ_BUSY || reset)) { | 660 if (!(busack==Z80_REQ_BUSY || reset)) { |
668 location &= 0x7FFF; | 661 location &= 0x7FFF; |
669 if (location < 0x4000) { | 662 if (location < 0x4000) { |
670 value = z80_ram[location & 0x1FFF]; | 663 value = z80_ram[location & 0x1FFF]; |
671 } else if (location < 0x6000) { | 664 } else if (location < 0x6000) { |
672 sync_sound(gen, context->current_cycle * MCLKS_PER_68K); | 665 sync_sound(gen, context->current_cycle); |
673 value = ym_read_status(gen->ym); | 666 value = ym_read_status(gen->ym); |
674 } else { | 667 } else { |
675 value = 0xFF; | 668 value = 0xFF; |
676 } | 669 } |
677 } else { | 670 } else { |
739 | 732 |
740 void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) | 733 void * z80_write_ym(uint32_t location, void * vcontext, uint8_t value) |
741 { | 734 { |
742 z80_context * context = vcontext; | 735 z80_context * context = vcontext; |
743 genesis_context * gen = context->system; | 736 genesis_context * gen = context->system; |
744 sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); | 737 sync_sound(gen, context->current_cycle); |
745 if (location & 1) { | 738 if (location & 1) { |
746 ym_data_write(gen->ym, value); | 739 ym_data_write(gen->ym, value); |
747 } else if (location & 2) { | 740 } else if (location & 2) { |
748 ym_address_write_part2(gen->ym, value); | 741 ym_address_write_part2(gen->ym, value); |
749 } else { | 742 } else { |
754 | 747 |
755 uint8_t z80_read_ym(uint32_t location, void * vcontext) | 748 uint8_t z80_read_ym(uint32_t location, void * vcontext) |
756 { | 749 { |
757 z80_context * context = vcontext; | 750 z80_context * context = vcontext; |
758 genesis_context * gen = context->system; | 751 genesis_context * gen = context->system; |
759 sync_sound(gen, context->current_cycle * MCLKS_PER_Z80); | 752 sync_sound(gen, context->current_cycle); |
760 return ym_read_status(gen->ym); | 753 return ym_read_status(gen->ym); |
761 } | 754 } |
762 | 755 |
763 uint8_t z80_read_bank(uint32_t location, void * vcontext) | 756 uint8_t z80_read_bank(uint32_t location, void * vcontext) |
764 { | 757 { |
765 z80_context * context = vcontext; | 758 z80_context * context = vcontext; |
766 //typical delay from bus arbitration | 759 //typical delay from bus arbitration |
767 context->current_cycle += 3; | 760 context->current_cycle += 3; |
768 | 761 |
769 location &= 0x7FFF; | 762 location &= 0x7FFF; |
770 //TODO: add cycle for an access right after a previous one | 763 //TODO: add cycle for an access right after a previous one |
771 //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access | 764 //TODO: block Z80 if VDP has the bus or the 68K is blocked on a VDP access |
772 if (context->mem_pointers[1]) { | 765 if (context->mem_pointers[1]) { |
773 return context->mem_pointers[1][location ^ 1]; | 766 return context->mem_pointers[1][location ^ 1]; |
802 } | 795 } |
803 | 796 |
804 void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) | 797 void *z80_write_bank_reg(uint32_t location, void * vcontext, uint8_t value) |
805 { | 798 { |
806 z80_context * context = vcontext; | 799 z80_context * context = vcontext; |
807 | 800 |
808 context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; | 801 context->bank_reg = (context->bank_reg >> 1 | value << 8) & 0x1FF; |
809 if (context->bank_reg < 0x80) { | 802 if (context->bank_reg < 0x80) { |
810 genesis_context *gen = context->system; | 803 genesis_context *gen = context->system; |
811 context->mem_pointers[1] = get_native_pointer(context->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); | 804 context->mem_pointers[1] = get_native_pointer(context->bank_reg << 15, (void **)gen->m68k->mem_pointers, &gen->m68k->options->gen); |
812 } else { | 805 } else { |
813 context->mem_pointers[1] = NULL; | 806 context->mem_pointers[1] = NULL; |
814 } | 807 } |
815 | 808 |
816 return context; | 809 return context; |
817 } | 810 } |
818 | 811 |
819 uint16_t read_sram_w(uint32_t address, m68k_context * context) | 812 uint16_t read_sram_w(uint32_t address, m68k_context * context) |
820 { | 813 { |
1082 printf("Loaded SRAM from %s\n", sram_filename); | 1075 printf("Loaded SRAM from %s\n", sram_filename); |
1083 } | 1076 } |
1084 } | 1077 } |
1085 atexit(save_sram); | 1078 atexit(save_sram); |
1086 } | 1079 } |
1087 init_m68k_opts(&opts, memmap, num_chunks); | 1080 init_m68k_opts(&opts, memmap, num_chunks, MCLKS_PER_68K); |
1088 opts.address_log = address_log; | 1081 opts.address_log = address_log; |
1089 init_68k_context(&context, opts.gen.native_code_map, &opts); | 1082 init_68k_context(&context, opts.gen.native_code_map, &opts); |
1090 | 1083 |
1091 context.video_context = gen->vdp; | 1084 context.video_context = gen->vdp; |
1092 context.system = gen; | 1085 context.system = gen; |
1093 //cartridge ROM | 1086 //cartridge ROM |
1094 context.mem_pointers[0] = cart; | 1087 context.mem_pointers[0] = cart; |
1095 context.target_cycle = context.sync_cycle = mclk_target/MCLKS_PER_68K; | 1088 context.target_cycle = context.sync_cycle = mclk_target; |
1096 //work RAM | 1089 //work RAM |
1097 context.mem_pointers[1] = ram; | 1090 context.mem_pointers[1] = ram; |
1098 //save RAM/map | 1091 //save RAM/map |
1099 context.mem_pointers[2] = initial_mapped; | 1092 context.mem_pointers[2] = initial_mapped; |
1100 context.mem_pointers[3] = (uint16_t *)gen->save_ram; | 1093 context.mem_pointers[3] = (uint16_t *)gen->save_ram; |
1367 psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); | 1360 psg_init(&p_context, render_sample_rate(), gen.master_clock, MCLKS_PER_PSG, render_audio_buffer()); |
1368 | 1361 |
1369 z80_context z_context; | 1362 z80_context z_context; |
1370 #ifndef NO_Z80 | 1363 #ifndef NO_Z80 |
1371 z80_options z_opts; | 1364 z80_options z_opts; |
1372 init_z80_opts(&z_opts, z80_map, 5); | 1365 init_z80_opts(&z_opts, z80_map, 5, MCLKS_PER_Z80); |
1373 init_z80_context(&z_context, &z_opts); | 1366 init_z80_context(&z_context, &z_opts); |
1374 #endif | 1367 #endif |
1375 | 1368 |
1376 z_context.system = &gen; | 1369 z_context.system = &gen; |
1377 z_context.mem_pointers[0] = z80_ram; | 1370 z_context.mem_pointers[0] = z80_ram; |
1378 z_context.sync_cycle = z_context.target_cycle = mclk_target/MCLKS_PER_Z80; | 1371 z_context.sync_cycle = z_context.target_cycle = mclk_target; |
1379 z_context.int_cycle = CYCLE_NEVER; | 1372 z_context.int_cycle = CYCLE_NEVER; |
1380 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; | 1373 z_context.mem_pointers[1] = z_context.mem_pointers[2] = (uint8_t *)cart; |
1381 | 1374 |
1382 gen.z80 = &z_context; | 1375 gen.z80 = &z_context; |
1383 gen.vdp = &v_context; | 1376 gen.vdp = &v_context; |