Mercurial > repos > blastem
comparison blastem.c @ 336:87b65e5ce1ab
Fix a stupid bug in z80 busreq acknowledge delay code and make some small improvements there too
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 14 May 2013 22:52:15 -0700 |
parents | 14a937097c2b |
children | 5c34a9c39394 |
comparison
equal
deleted
inserted
replaced
335:14a937097c2b | 336:87b65e5ce1ab |
---|---|
379 }*/ | 379 }*/ |
380 } | 380 } |
381 | 381 |
382 uint32_t zram_counter = 0; | 382 uint32_t zram_counter = 0; |
383 #define Z80_ACK_DELAY 3 | 383 #define Z80_ACK_DELAY 3 |
384 #define Z80_BUSY_DELAY 2//TODO: Find the actual value for this | 384 #define Z80_BUSY_DELAY 1//TODO: Find the actual value for this |
385 #define Z80_REQ_BUSY 1 | 385 #define Z80_REQ_BUSY 1 |
386 #define Z80_REQ_ACK 0 | 386 #define Z80_REQ_ACK 0 |
387 #define Z80_RES_BUSACK reset | 387 #define Z80_RES_BUSACK reset |
388 | 388 |
389 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) | 389 m68k_context * io_write(uint32_t location, m68k_context * context, uint8_t value) |
390 { | 390 { |
391 genesis_context * gen = context->system; | 391 genesis_context * gen = context->system; |
392 if (location < 0x10000) { | 392 if (location < 0x10000) { |
393 if (busack_cycle > context->current_cycle) { | 393 if (busack_cycle <= context->current_cycle) { |
394 busack = new_busack; | 394 busack = new_busack; |
395 busack_cycle = CYCLE_NEVER; | 395 busack_cycle = CYCLE_NEVER; |
396 } | 396 } |
397 if (!(busack || reset)) { | 397 if (!(busack || reset)) { |
398 location &= 0x7FFF; | 398 location &= 0x7FFF; |
431 break; | 431 break; |
432 } | 432 } |
433 } else { | 433 } else { |
434 if (location == 0x1100) { | 434 if (location == 0x1100) { |
435 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 435 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
436 if (busack_cycle > context->current_cycle) { | 436 if (busack_cycle <= context->current_cycle) { |
437 busack = new_busack; | 437 busack = new_busack; |
438 busack_cycle = CYCLE_NEVER; | 438 busack_cycle = CYCLE_NEVER; |
439 } | 439 } |
440 if (value & 1) { | 440 if (value & 1) { |
441 dputs("bus requesting Z80"); | 441 dputs("bus requesting Z80"); |
442 busreq = 1; | 442 |
443 if(!reset) { | 443 if(!reset && !busreq) { |
444 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; | 444 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//context->current_cycle + Z80_ACK_DELAY; |
445 new_busack = Z80_REQ_ACK; | 445 new_busack = Z80_REQ_ACK; |
446 busreq = 1; | |
446 } | 447 } |
447 } else { | 448 } else { |
448 if (busreq) { | 449 if (busreq) { |
449 dputs("releasing z80 bus"); | 450 dputs("releasing z80 bus"); |
450 #ifdef DO_DEBUG_PRINT | 451 #ifdef DO_DEBUG_PRINT |
452 sprintf(fname, "zram-%d", zram_counter++); | 453 sprintf(fname, "zram-%d", zram_counter++); |
453 FILE * f = fopen(fname, "wb"); | 454 FILE * f = fopen(fname, "wb"); |
454 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 455 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
455 fclose(f); | 456 fclose(f); |
456 #endif | 457 #endif |
457 //TODO: Add necessary delay between release of busreq and resumption of execution | 458 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; |
458 } | 459 new_busack = Z80_REQ_BUSY; |
459 busreq = 0; | 460 busreq = 0; |
461 } | |
460 //busack_cycle = CYCLE_NEVER; | 462 //busack_cycle = CYCLE_NEVER; |
461 //busack = Z80_REQ_BUSY; | 463 //busack = Z80_REQ_BUSY; |
462 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; | 464 |
463 new_busack = Z80_REQ_BUSY; | |
464 } | 465 } |
465 } else if (location == 0x1200) { | 466 } else if (location == 0x1200) { |
466 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 467 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
467 if (value & 1) { | 468 if (value & 1) { |
468 if (reset && busreq) { | 469 if (reset && busreq) { |
487 | 488 |
488 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) | 489 m68k_context * io_write_w(uint32_t location, m68k_context * context, uint16_t value) |
489 { | 490 { |
490 genesis_context * gen = context->system; | 491 genesis_context * gen = context->system; |
491 if (location < 0x10000) { | 492 if (location < 0x10000) { |
492 if (busack_cycle > context->current_cycle) { | 493 if (busack_cycle <= context->current_cycle) { |
493 busack = new_busack; | 494 busack = new_busack; |
494 busack_cycle = CYCLE_NEVER; | 495 busack_cycle = CYCLE_NEVER; |
495 } | 496 } |
496 if (!(busack || reset)) { | 497 if (!(busack || reset)) { |
497 location &= 0x7FFF; | 498 location &= 0x7FFF; |
531 } | 532 } |
532 } else { | 533 } else { |
533 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle); | 534 //printf("IO Write of %X to %X @ %d\n", value, location, context->current_cycle); |
534 if (location == 0x1100) { | 535 if (location == 0x1100) { |
535 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 536 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
536 if (busack_cycle > context->current_cycle) { | 537 if (busack_cycle <= context->current_cycle) { |
537 busack = new_busack; | 538 busack = new_busack; |
538 busack_cycle = CYCLE_NEVER; | 539 busack_cycle = CYCLE_NEVER; |
539 } | 540 } |
540 if (value & 0x100) { | 541 if (value & 0x100) { |
541 dprintf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); | 542 dprintf("bus requesting Z80 @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); |
542 busreq = 1; | 543 |
543 if(!reset) { | 544 if(!reset && !busreq) { |
544 busack_cycle = ((gen->z80->current_cycle + Z80_ACK_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K;//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; |
545 new_busack = Z80_REQ_ACK; | 546 new_busack = Z80_REQ_ACK; |
547 busreq = 1; | |
546 } | 548 } |
547 } else { | 549 } else { |
548 if (busreq) { | 550 if (busreq) { |
549 dprintf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); | 551 dprintf("releasing Z80 bus @ %d\n", (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80); |
550 #ifdef DO_DEBUG_PRINT | 552 #ifdef DO_DEBUG_PRINT |
552 sprintf(fname, "zram-%d", zram_counter++); | 554 sprintf(fname, "zram-%d", zram_counter++); |
553 FILE * f = fopen(fname, "wb"); | 555 FILE * f = fopen(fname, "wb"); |
554 fwrite(z80_ram, 1, sizeof(z80_ram), f); | 556 fwrite(z80_ram, 1, sizeof(z80_ram), f); |
555 fclose(f); | 557 fclose(f); |
556 #endif | 558 #endif |
557 //TODO: Add necessary delay between release of busreq and resumption of execution | 559 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; |
558 } | 560 new_busack = Z80_REQ_BUSY; |
559 busreq = 0; | 561 busreq = 0; |
562 } | |
560 //busack_cycle = CYCLE_NEVER; | 563 //busack_cycle = CYCLE_NEVER; |
561 //busack = Z80_REQ_BUSY; | 564 //busack = Z80_REQ_BUSY; |
562 busack_cycle = ((gen->z80->current_cycle + Z80_BUSY_DELAY) * MCLKS_PER_Z80) / MCLKS_PER_68K; | |
563 new_busack = Z80_REQ_BUSY; | |
564 } | 565 } |
565 } else if (location == 0x1200) { | 566 } else if (location == 0x1200) { |
566 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); | 567 sync_z80(gen->z80, context->current_cycle * MCLKS_PER_68K); |
567 if (value & 0x100) { | 568 if (value & 0x100) { |
568 if (reset && busreq) { | 569 if (reset && busreq) { |
571 } | 572 } |
572 //TODO: Deal with the scenario in which reset is not asserted long enough | 573 //TODO: Deal with the scenario in which reset is not asserted long enough |
573 if (reset) { | 574 if (reset) { |
574 need_reset = 1; | 575 need_reset = 1; |
575 //TODO: Add necessary delay between release of reset and start of execution | 576 //TODO: Add necessary delay between release of reset and start of execution |
577 gen->z80->current_cycle = (context->current_cycle * MCLKS_PER_68K) / MCLKS_PER_Z80; | |
576 } | 578 } |
577 reset = 0; | 579 reset = 0; |
578 } else { | 580 } else { |
579 reset = 1; | 581 reset = 1; |
580 } | 582 } |
592 | 594 |
593 m68k_context * io_read(uint32_t location, m68k_context * context) | 595 m68k_context * io_read(uint32_t location, m68k_context * context) |
594 { | 596 { |
595 genesis_context *gen = context->system; | 597 genesis_context *gen = context->system; |
596 if (location < 0x10000) { | 598 if (location < 0x10000) { |
597 if (busack_cycle > context->current_cycle) { | 599 if (busack_cycle <= context->current_cycle) { |
598 busack = new_busack; | 600 busack = new_busack; |
599 busack_cycle = CYCLE_NEVER; | 601 busack_cycle = CYCLE_NEVER; |
600 } | 602 } |
601 if (!(busack==Z80_REQ_BUSY || reset)) { | 603 if (!(busack==Z80_REQ_BUSY || reset)) { |
602 location &= 0x7FFF; | 604 location &= 0x7FFF; |
636 context->value = gamepad_2.control; | 638 context->value = gamepad_2.control; |
637 break; | 639 break; |
638 } | 640 } |
639 } else { | 641 } else { |
640 if (location == 0x1100) { | 642 if (location == 0x1100) { |
641 if (busack_cycle > context->current_cycle) { | 643 if (busack_cycle <= context->current_cycle) { |
642 busack = new_busack; | 644 busack = new_busack; |
643 busack_cycle = CYCLE_NEVER; | 645 busack_cycle = CYCLE_NEVER; |
644 } | 646 } |
645 context->value = Z80_RES_BUSACK || busack; | 647 context->value = Z80_RES_BUSACK || busack; |
646 //printf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d)\n", context->value, context->current_cycle, reset, busack); | 648 dprintf("Byte read of BUSREQ returned %d @ %d (reset: %d, busack: %d, busack_cycle %d)\n", context->value, context->current_cycle, reset, busack, busack_cycle); |
647 } else if (location == 0x1200) { | 649 } else if (location == 0x1200) { |
648 context->value = !reset; | 650 context->value = !reset; |
649 } else { | 651 } else { |
650 printf("Byte read of unknown IO location: %X\n", location); | 652 printf("Byte read of unknown IO location: %X\n", location); |
651 } | 653 } |
656 | 658 |
657 m68k_context * io_read_w(uint32_t location, m68k_context * context) | 659 m68k_context * io_read_w(uint32_t location, m68k_context * context) |
658 { | 660 { |
659 genesis_context * gen = context->system; | 661 genesis_context * gen = context->system; |
660 if (location < 0x10000) { | 662 if (location < 0x10000) { |
661 if (busack_cycle > context->current_cycle) { | 663 if (busack_cycle <= context->current_cycle) { |
662 busack = new_busack; | 664 busack = new_busack; |
663 busack_cycle = CYCLE_NEVER; | 665 busack_cycle = CYCLE_NEVER; |
664 } | 666 } |
665 if (!(busack==Z80_REQ_BUSY || reset)) { | 667 if (!(busack==Z80_REQ_BUSY || reset)) { |
666 location &= 0x7FFF; | 668 location &= 0x7FFF; |
708 } | 710 } |
709 context->value = context->value | (context->value << 8); | 711 context->value = context->value | (context->value << 8); |
710 //printf("Word read to %X returned %d\n", location, context->value); | 712 //printf("Word read to %X returned %d\n", location, context->value); |
711 } else { | 713 } else { |
712 if (location == 0x1100) { | 714 if (location == 0x1100) { |
713 if (busack_cycle > context->current_cycle) { | 715 if (busack_cycle <= context->current_cycle) { |
714 busack = new_busack; | 716 busack = new_busack; |
715 busack_cycle = CYCLE_NEVER; | 717 busack_cycle = CYCLE_NEVER; |
716 } | 718 } |
717 context->value = (Z80_RES_BUSACK || busack) << 8; | 719 context->value = (Z80_RES_BUSACK || busack) << 8; |
718 //printf("Word read of BUSREQ returned %d\n", context->value); | 720 //printf("Word read of BUSREQ returned %d\n", context->value); |