Mercurial > repos > blastem
comparison blastem.c @ 289:1cc0850ab6bc
Hopefully more correct implementation of the Z80 busack status
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Mon, 06 May 2013 00:22:24 -0700 |
parents | a8ee7934a1f8 |
children | 171f97e70d85 |
comparison
equal
deleted
inserted
replaced
288:a8ee7934a1f8 | 289:1cc0850ab6bc |
---|---|
123 } | 123 } |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 int break_on_sync = 0; | 127 int break_on_sync = 0; |
128 #define Z80_ACK_DELAY 3 //TODO: Calculate this on the fly based on how synced up the Z80 and 68K clocks are | |
129 | 128 |
130 uint8_t reset = 1; | 129 uint8_t reset = 1; |
131 uint8_t need_reset = 0; | 130 uint8_t need_reset = 0; |
132 uint8_t busreq = 0; | 131 uint8_t busreq = 0; |
133 uint8_t busack = 0; | 132 uint8_t busack = 0; |
157 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; | 156 z_context->target_cycle = z_context->sync_cycle < z_context->int_cycle ? z_context->sync_cycle : z_context->int_cycle; |
158 dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); | 157 dprintf("Running Z80 from cycle %d to cycle %d. Native PC: %p\n", z_context->current_cycle, z_context->sync_cycle, z_context->native_pc); |
159 z80_run(z_context); | 158 z80_run(z_context); |
160 dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); | 159 dprintf("Z80 ran to cycle %d\n", z_context->current_cycle); |
161 } | 160 } |
161 } else { | |
162 z_context->current_cycle = mclks / MCLKS_PER_Z80; | |
162 } | 163 } |
163 } | 164 } |
164 | 165 |
165 m68k_context * sync_components(m68k_context * context, uint32_t address) | 166 m68k_context * sync_components(m68k_context * context, uint32_t address) |
166 { | 167 { |
352 printf ("value: %X\n", context->value); | 353 printf ("value: %X\n", context->value); |
353 }*/ | 354 }*/ |
354 } | 355 } |
355 | 356 |
356 uint32_t zram_counter = 0; | 357 uint32_t zram_counter = 0; |
358 #define Z80_ACK_DELAY 3 | |
359 #define Z80_BUSY_DELAY 2//TODO: Find the actual value for this | |
360 #define Z80_REQ_BUSY 1 | |
361 #define Z80_REQ_ACK 0 | |
362 #define Z80_RES_BUSACK reset | |
357 | 363 |
358 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | 364 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) |
359 { | 365 { |
360 genesis_context * gen = context->system; | 366 genesis_context * gen = context->system; |
361 if (location < 0x10000) { | 367 if (location < 0x10000) { |
408 } | 414 } |
409 if (value & 1) { | 415 if (value & 1) { |
410 dputs("bus requesting Z80"); | 416 dputs("bus requesting Z80"); |
411 busreq = 1; | 417 busreq = 1; |
412 if(!reset) { | 418 if(!reset) { |
413 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 419 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; |
414 new_busack = 0; | 420 new_busack = Z80_REQ_ACK; |
415 } | 421 } |
416 } else { | 422 } else { |
417 if (busreq) { | 423 if (busreq) { |
418 dputs("releasing z80 bus"); | 424 dputs("releasing z80 bus"); |
419 #ifdef DO_DEBUG_PRINT | 425 #ifdef DO_DEBUG_PRINT |
422 FILE * f = fopen(fname, "wb"); | 428 FILE * f = fopen(fname, "wb"); |
423 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 429 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
424 fclose(f); | 430 fclose(f); |
425 #endif | 431 #endif |
426 //TODO: Add necessary delay between release of busreq and resumption of execution | 432 //TODO: Add necessary delay between release of busreq and resumption of execution |
427 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; | |
428 } | 433 } |
429 busreq = 0; | 434 busreq = 0; |
430 busack_cycle = CYCLE_NEVER; | 435 //busack_cycle = CYCLE_NEVER; |
431 busack = 1; | 436 //busack = Z80_REQ_BUSY; |
437 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; | |
438 new_busack = Z80_REQ_BUSY; | |
432 } | 439 } |
433 } else if (location == 0x1200) { | 440 } else if (location == 0x1200) { |
434 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 441 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
435 if (value & 1) { | 442 if (value & 1) { |
436 if (reset && busreq) { | 443 if (reset && busreq) { |
437 new_busack = 0; | 444 new_busack = 0; |
438 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 445 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; |
439 } | 446 } |
440 //TODO: Deal with the scenario in which reset is not asserted long enough | 447 //TODO: Deal with the scenario in which reset is not asserted long enough |
441 if (reset) { | 448 if (reset) { |
442 need_reset = 1; | 449 need_reset = 1; |
443 //TODO: Add necessary delay between release of reset and start of execution | 450 //TODO: Add necessary delay between release of reset and start of execution |
507 } | 514 } |
508 if (value & 0x100) { | 515 if (value & 0x100) { |
509 dprintf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); | 516 dprintf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); |
510 busreq = 1; | 517 busreq = 1; |
511 if(!reset) { | 518 if(!reset) { |
512 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 519 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; |
513 new_busack = 0; | 520 new_busack = Z80_REQ_ACK; |
514 } | 521 } |
515 } else { | 522 } else { |
516 if (busreq) { | 523 if (busreq) { |
517 dprintf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); | 524 dprintf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); |
518 #ifdef DO_DEBUG_PRINT | 525 #ifdef DO_DEBUG_PRINT |
521 FILE * f = fopen(fname, "wb"); | 528 FILE * f = fopen(fname, "wb"); |
522 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 529 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
523 fclose(f); | 530 fclose(f); |
524 #endif | 531 #endif |
525 //TODO: Add necessary delay between release of busreq and resumption of execution | 532 //TODO: Add necessary delay between release of busreq and resumption of execution |
526 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; | |
527 } | 533 } |
528 busreq = 0; | 534 busreq = 0; |
529 busack_cycle = CYCLE_NEVER; | 535 //busack_cycle = CYCLE_NEVER; |
530 busack = 1; | 536 //busack = Z80_REQ_BUSY; |
537 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; | |
538 new_busack = Z80_REQ_BUSY; | |
531 } | 539 } |
532 } else if (location == 0x1200) { | 540 } else if (location == 0x1200) { |
533 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 541 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
534 if (value & 0x100) { | 542 if (value & 0x100) { |
535 if (reset && busreq) { | 543 if (reset && busreq) { |
536 new_busack = 0; | 544 new_busack = 0; |
537 busack_cycle = context->current_cycle + Z80_ACK_DELAY; | 545 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; |
538 } | 546 } |
539 //TODO: Deal with the scenario in which reset is not asserted long enough | 547 //TODO: Deal with the scenario in which reset is not asserted long enough |
540 if (reset) { | 548 if (reset) { |
541 need_reset = 1; | 549 need_reset = 1; |
542 //TODO: Add necessary delay between release of reset and start of execution | 550 //TODO: Add necessary delay between release of reset and start of execution |
543 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; | |
544 } | 551 } |
545 reset = 0; | 552 reset = 0; |
546 } else { | 553 } else { |
547 reset = 1; | 554 reset = 1; |
548 } | 555 } |
564 if (location < 0x10000) { | 571 if (location < 0x10000) { |
565 if (busack_cycle > context->current_cycle) { | 572 if (busack_cycle > context->current_cycle) { |
566 busack = new_busack; | 573 busack = new_busack; |
567 busack_cycle = CYCLE_NEVER; | 574 busack_cycle = CYCLE_NEVER; |
568 } | 575 } |
569 if (!(busack || reset)) { | 576 if (!(busack==Z80_REQ_BUSY || reset)) { |
570 location &= 0x7FFF; | 577 location &= 0x7FFF; |
571 if (location < 0x4000) { | 578 if (location < 0x4000) { |
572 context->value = z80_ram[location & 0x1FFF]; | 579 context->value = z80_ram[location & 0x1FFF]; |
573 } else if (location < 0x6000) { | 580 } else if (location < 0x6000) { |
574 ym_run(gen->ym, context->current_cycle); | 581 ym_run(gen->ym, context->current_cycle); |
608 if (location == 0x1100) { | 615 if (location == 0x1100) { |
609 if (busack_cycle > context->current_cycle) { | 616 if (busack_cycle > context->current_cycle) { |
610 busack = new_busack; | 617 busack = new_busack; |
611 busack_cycle = CYCLE_NEVER; | 618 busack_cycle = CYCLE_NEVER; |
612 } | 619 } |
613 context->value = reset || busack; | 620 context->value = Z80_RES_BUSACK || busack; |
614 //printf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d)\n", context->value, context->current_cycle, reset, busack); | 621 //printf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d)\n", context->value, context->current_cycle, reset, busack); |
615 } else if (location == 0x1200) { | 622 } else if (location == 0x1200) { |
616 context->value = !reset; | 623 context->value = !reset; |
617 } else { | 624 } else { |
618 printf("Byte read of unknown IO location: %X\n", location); | 625 printf("Byte read of unknown IO location: %X\n", location); |
628 if (location < 0x10000) { | 635 if (location < 0x10000) { |
629 if (busack_cycle > context->current_cycle) { | 636 if (busack_cycle > context->current_cycle) { |
630 busack = new_busack; | 637 busack = new_busack; |
631 busack_cycle = CYCLE_NEVER; | 638 busack_cycle = CYCLE_NEVER; |
632 } | 639 } |
633 if (!(busack || reset)) { | 640 if (!(busack==Z80_REQ_BUSY || reset)) { |
634 location &= 0x7FFF; | 641 location &= 0x7FFF; |
635 uint16_t value; | 642 uint16_t value; |
636 if (location < 0x4000) { | 643 if (location < 0x4000) { |
637 value = z80_ram[location & 0x1FFE]; | 644 value = z80_ram[location & 0x1FFE]; |
638 } else if (location < 0x6000) { | 645 } else if (location < 0x6000) { |
680 if (location == 0x1100) { | 687 if (location == 0x1100) { |
681 if (busack_cycle > context->current_cycle) { | 688 if (busack_cycle > context->current_cycle) { |
682 busack = new_busack; | 689 busack = new_busack; |
683 busack_cycle = CYCLE_NEVER; | 690 busack_cycle = CYCLE_NEVER; |
684 } | 691 } |
685 context->value = (reset || busack) << 8; | 692 context->value = (Z80_RES_BUSACK || busack) << 8; |
686 //printf("Word read of BUSREQ returned %d\n", context->value); | 693 //printf("Word read of BUSREQ returned %d\n", context->value); |
687 } else if (location == 0x1200) { | 694 } else if (location == 0x1200) { |
688 context->value = (!reset) << 8; | 695 context->value = (!reset) << 8; |
689 } else { | 696 } else { |
690 printf("Word read of unknown IO location: %X\n", location); | 697 printf("Word read of unknown IO location: %X\n", location); |