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;