Mercurial > repos > blastem
comparison segacd.c @ 2066:a61a8a87410c segacd
Fix a bunch of CDC/CDD related mcd-verificator failures
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Sun, 30 Jan 2022 00:21:58 -0800 |
parents | 02a9846668d1 |
children | f573f2c31bc9 |
comparison
equal
deleted
inserted
replaced
2065:02a9846668d1 | 2066:a61a8a87410c |
---|---|
330 context->int_cycle = CYCLE_NEVER; | 330 context->int_cycle = CYCLE_NEVER; |
331 uint8_t mask = context->status & 0x7; | 331 uint8_t mask = context->status & 0x7; |
332 if (mask < 5) { | 332 if (mask < 5) { |
333 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) { | 333 if (cd->gate_array[GA_INT_MASK] & BIT_MASK_IEN5) { |
334 uint32_t cdc_cycle = lc8951_next_interrupt(&cd->cdc); | 334 uint32_t cdc_cycle = lc8951_next_interrupt(&cd->cdc); |
335 //CDC interrupts only generated on falling edge of !INT signal | |
336 if (cd->cdc_int_ack) { | |
337 if (cdc_cycle > cd->cdc.cycle) { | |
338 cd->cdc_int_ack = 0; | |
339 } else { | |
340 cdc_cycle = CYCLE_NEVER; | |
341 } | |
342 } | |
335 if (cdc_cycle < context->int_cycle) { | 343 if (cdc_cycle < context->int_cycle) { |
336 context->int_cycle = cdc_cycle; | 344 context->int_cycle = cdc_cycle; |
337 context->int_num = 5; | 345 context->int_num = 5; |
338 } | 346 } |
339 } | 347 } |
399 return cd->gate_array[reg] | cd->cdc.ar; | 407 return cd->gate_array[reg] | cd->cdc.ar; |
400 case GA_CDC_REG_DATA: | 408 case GA_CDC_REG_DATA: |
401 cdd_run(cd, m68k->current_cycle); | 409 cdd_run(cd, m68k->current_cycle); |
402 return lc8951_reg_read(&cd->cdc); | 410 return lc8951_reg_read(&cd->cdc); |
403 case GA_CDC_HOST_DATA: { | 411 case GA_CDC_HOST_DATA: { |
412 cdd_run(cd, m68k->current_cycle); | |
404 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; | 413 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; |
405 if (dst == DST_SUB_CPU) { | 414 if (dst == DST_SUB_CPU) { |
406 cdd_run(cd, m68k->current_cycle); | |
407 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { | 415 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { |
408 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR; | 416 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR; |
409 lc8951_resume_transfer(&cd->cdc); | 417 lc8951_resume_transfer(&cd->cdc, cd->cdc.cycle); |
410 } | 418 } |
411 calculate_target_cycle(cd->m68k); | 419 calculate_target_cycle(cd->m68k); |
412 return cd->gate_array[reg]; | 420 |
413 } else { | 421 } |
414 return 0xFFFF; | 422 return cd->gate_array[reg]; |
415 } | |
416 } | 423 } |
417 case GA_STOP_WATCH: | 424 case GA_STOP_WATCH: |
418 case GA_TIMER: | 425 case GA_TIMER: |
419 timers_run(cd, m68k->current_cycle); | 426 timers_run(cd, m68k->current_cycle); |
420 return cd->gate_array[reg]; | 427 return cd->gate_array[reg]; |
525 break; | 532 break; |
526 } | 533 } |
527 case GA_CDC_CTRL: | 534 case GA_CDC_CTRL: |
528 cdd_run(cd, m68k->current_cycle); | 535 cdd_run(cd, m68k->current_cycle); |
529 lc8951_ar_write(&cd->cdc, value); | 536 lc8951_ar_write(&cd->cdc, value); |
530 cd->gate_array[reg] &= 0xC000; | 537 //cd->gate_array[reg] &= 0xC000; |
538 //apparently this clears EDT, should it also clear DSR? | |
531 cd->gate_array[reg] = value & 0x0700; | 539 cd->gate_array[reg] = value & 0x0700; |
540 cd->cdc_dst_low = 0; | |
532 break; | 541 break; |
533 case GA_CDC_REG_DATA: | 542 case GA_CDC_REG_DATA: |
534 cdd_run(cd, m68k->current_cycle); | 543 cdd_run(cd, m68k->current_cycle); |
544 printf("CDC write %X: %X @ %u\n", cd->cdc.ar, value, m68k->current_cycle); | |
535 lc8951_reg_write(&cd->cdc, value); | 545 lc8951_reg_write(&cd->cdc, value); |
536 calculate_target_cycle(m68k); | 546 calculate_target_cycle(m68k); |
537 break; | 547 break; |
538 case GA_CDC_DMA_ADDR: | 548 case GA_CDC_DMA_ADDR: |
539 cdd_run(cd, m68k->current_cycle); | 549 cdd_run(cd, m68k->current_cycle); |
628 value16 = value | (value << 8); | 638 value16 = value | (value << 8); |
629 break; | 639 break; |
630 case GA_CDC_CTRL: | 640 case GA_CDC_CTRL: |
631 if (address & 1) { | 641 if (address & 1) { |
632 lc8951_ar_write(&cd->cdc, value); | 642 lc8951_ar_write(&cd->cdc, value); |
643 return vcontext; | |
633 } else { | 644 } else { |
634 cd->gate_array[reg] = value << 8; | 645 value16 = cd->cdc.ar | (value << 8); |
635 } | 646 } |
636 return vcontext; | 647 break; |
637 case GA_CDD_CMD4: | 648 case GA_CDD_CMD4: |
638 if (!address) { | 649 if (!address) { |
639 //byte write to $FF804A should not trigger transfer | 650 //byte write to $FF804A should not trigger transfer |
640 cdd_run(cd, m68k->current_cycle); | 651 cdd_run(cd, m68k->current_cycle); |
641 cd->gate_array[reg] &= 0x0F; | 652 cd->gate_array[reg] &= 0x0F; |
654 } | 665 } |
655 | 666 |
656 static uint8_t handle_cdc_byte(void *vsys, uint8_t value) | 667 static uint8_t handle_cdc_byte(void *vsys, uint8_t value) |
657 { | 668 { |
658 segacd_context *cd = vsys; | 669 segacd_context *cd = vsys; |
670 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { | |
671 //host reg is already full, pause transfer | |
672 return 0; | |
673 } | |
674 if (cd->cdc.cycle == cd->cdc.transfer_end) { | |
675 cd->gate_array[GA_CDC_CTRL] |= BIT_EDT; | |
676 printf("EDT set at %u\n", cd->cdc.cycle); | |
677 } | |
659 uint16_t dest = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; | 678 uint16_t dest = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; |
679 if (!(cd->cdc_dst_low & 1)) { | |
680 cd->gate_array[GA_CDC_HOST_DATA] &= 0xFF; | |
681 cd->gate_array[GA_CDC_HOST_DATA] |= value << 8; | |
682 cd->cdc_dst_low++; | |
683 if (dest != DST_PCM_RAM) { | |
684 //PCM RAM writes a byte at a time | |
685 return 1; | |
686 } | |
687 } else { | |
688 cd->gate_array[GA_CDC_HOST_DATA] &= 0xFF00; | |
689 cd->gate_array[GA_CDC_HOST_DATA] |= value; | |
690 } | |
691 | |
660 uint32_t dma_addr = cd->gate_array[GA_CDC_DMA_ADDR] << 3; | 692 uint32_t dma_addr = cd->gate_array[GA_CDC_DMA_ADDR] << 3; |
661 dma_addr |= cd->cdc_dst_low; | 693 dma_addr |= cd->cdc_dst_low; |
662 switch (dest) | 694 switch (dest) |
663 { | 695 { |
664 case DST_MAIN_CPU: | 696 case DST_MAIN_CPU: |
665 case DST_SUB_CPU: | 697 case DST_SUB_CPU: |
666 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { | 698 cd->cdc_dst_low = 0; |
667 //host reg is already full, pause transfer | 699 cd->gate_array[GA_CDC_CTRL] |= BIT_DSR; |
668 return 0; | 700 printf("DSR set at %u, (transfer_end %u, dbcl %X, dbch %X)\n", cd->cdc.cycle, cd->cdc.transfer_end, cd->cdc.regs[2], cd->cdc.regs[3]); |
669 } | |
670 if (cd->cdc_dst_low) { | |
671 cd->gate_array[GA_CDC_HOST_DATA] &= 0xFF00; | |
672 cd->gate_array[GA_CDC_HOST_DATA] |= value; | |
673 cd->cdc_dst_low = 0; | |
674 cd->gate_array[GA_CDC_CTRL] |= BIT_DSR; | |
675 } else { | |
676 cd->gate_array[GA_CDC_HOST_DATA] &= 0xFF; | |
677 cd->gate_array[GA_CDC_HOST_DATA] |= value << 8; | |
678 cd->cdc_dst_low = 1; | |
679 return 1; | |
680 } | |
681 break; | 701 break; |
682 case DST_PCM_RAM: | 702 case DST_PCM_RAM: |
683 dma_addr &= (1 << 13) - 1; | 703 dma_addr &= (1 << 13) - 1; |
684 //TODO: write to currently visible 8K bank of PCM RAM I guess? | 704 //TODO: write to currently visible 8K bank of PCM RAM I guess? |
685 dma_addr++; | 705 dma_addr += 2; |
686 cd->cdc_dst_low = dma_addr & 7; | 706 cd->cdc_dst_low = dma_addr & 7; |
687 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; | 707 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; |
688 break; | 708 break; |
689 case DST_PROG_RAM: | 709 case DST_PROG_RAM: |
690 ((uint8_t*)cd->prog_ram)[dma_addr ^ 1] = value; | 710 cd->prog_ram[dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; |
691 m68k_invalidate_code_range(cd->m68k, dma_addr, dma_addr + 1); | 711 m68k_invalidate_code_range(cd->m68k, dma_addr - 1, dma_addr + 1); |
692 dma_addr++; | 712 dma_addr++; |
693 cd->cdc_dst_low = dma_addr & 7; | 713 cd->cdc_dst_low = dma_addr & 7; |
694 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; | 714 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; |
695 break; | 715 break; |
696 case DST_WORD_RAM: | 716 case DST_WORD_RAM: |
697 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { | 717 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { |
698 //1M mode, write to bank assigned to Sub CPU | 718 //1M mode, write to bank assigned to Sub CPU |
699 dma_addr &= (1 << 17) - 1; | 719 dma_addr &= (1 << 17) - 1; |
700 ((uint8_t*)cd->m68k->mem_pointers[1])[dma_addr ^ 1] = value; | 720 cd->m68k->mem_pointers[1][dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; |
701 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr, 0x0C0000 + dma_addr + 1); | 721 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1); |
702 } else { | 722 } else { |
703 //2M mode, check if Sub CPU has access | 723 //2M mode, check if Sub CPU has access |
704 if (!(cd->gate_array[GA_MEM_MODE] & BIT_RET)) { | 724 if (!(cd->gate_array[GA_MEM_MODE] & BIT_RET)) { |
705 dma_addr &= (1 << 18) - 1; | 725 dma_addr &= (1 << 18) - 1; |
706 ((uint8_t*)cd->word_ram)[dma_addr ^ 1] = value; | 726 cd->word_ram[dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; |
707 m68k_invalidate_code_range(cd->m68k, 0x080000 + dma_addr, 0x080000 + dma_addr + 1); | 727 m68k_invalidate_code_range(cd->m68k, 0x080000 + dma_addr, 0x080000 + dma_addr + 1); |
708 } | 728 } |
709 } | 729 } |
710 dma_addr++; | 730 dma_addr++; |
711 cd->cdc_dst_low = dma_addr & 7; | 731 cd->cdc_dst_low = dma_addr & 7; |
712 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; | 732 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; |
713 break; | 733 break; |
714 default: | 734 default: |
715 printf("Invalid CDC transfer destination %d\n", dest); | 735 printf("Invalid CDC transfer destination %d\n", dest); |
716 } | |
717 if (cd->cdc.cycle == cd->cdc.transfer_end) { | |
718 cd->gate_array[GA_CDC_CTRL] |= BIT_EDT; | |
719 } | 736 } |
720 return 1; | 737 return 1; |
721 } | 738 } |
722 | 739 |
723 static uint8_t can_main_access_prog(segacd_context *cd) | 740 static uint8_t can_main_access_prog(segacd_context *cd) |
744 case 3: | 761 case 3: |
745 cd->timer_pending = 0; | 762 cd->timer_pending = 0; |
746 break; | 763 break; |
747 case 4: | 764 case 4: |
748 cd->cdd.int_pending = 0; | 765 cd->cdd.int_pending = 0; |
766 break; | |
767 case 5: | |
768 cd->cdc_int_ack = 1; | |
769 break; | |
749 } | 770 } |
750 context->int_ack = 0; | 771 context->int_ack = 0; |
751 calculate_target_cycle(context); | 772 calculate_target_cycle(context); |
752 return context; | 773 return context; |
753 } | 774 } |
754 | 775 |
755 void scd_run(segacd_context *cd, uint32_t cycle) | 776 void scd_run(segacd_context *cd, uint32_t cycle) |
756 { | 777 { |
757 uint8_t m68k_run = !can_main_access_prog(cd); | 778 uint8_t m68k_run = !can_main_access_prog(cd); |
758 if (m68k_run) { | 779 if (cycle > cd->m68k->current_cycle) { |
759 cd->m68k->sync_cycle = cycle; | 780 if (m68k_run) { |
760 if (cd->need_reset) { | 781 uint32_t start = cd->m68k->current_cycle; |
761 cd->need_reset = 0; | 782 cd->m68k->sync_cycle = cycle; |
762 m68k_reset(cd->m68k); | 783 if (cd->need_reset) { |
784 cd->need_reset = 0; | |
785 m68k_reset(cd->m68k); | |
786 } else { | |
787 calculate_target_cycle(cd->m68k); | |
788 resume_68k(cd->m68k); | |
789 } | |
763 } else { | 790 } else { |
764 calculate_target_cycle(cd->m68k); | 791 cd->m68k->current_cycle = cycle; |
765 resume_68k(cd->m68k); | 792 } |
766 } | |
767 } else { | |
768 cd->m68k->current_cycle = cycle; | |
769 } | 793 } |
770 scd_peripherals_run(cd, cycle); | 794 scd_peripherals_run(cd, cycle); |
771 } | 795 } |
772 | 796 |
773 uint32_t gen_cycle_to_scd(uint32_t cycle, genesis_context *gen) | 797 uint32_t gen_cycle_to_scd(uint32_t cycle, genesis_context *gen) |
789 cd->periph_reset_cycle = CYCLE_NEVER; | 813 cd->periph_reset_cycle = CYCLE_NEVER; |
790 } else if (cd->periph_reset_cycle != CYCLE_NEVER) { | 814 } else if (cd->periph_reset_cycle != CYCLE_NEVER) { |
791 cd->periph_reset_cycle -= deduction; | 815 cd->periph_reset_cycle -= deduction; |
792 } | 816 } |
793 cdd_mcu_adjust_cycle(&cd->cdd, deduction); | 817 cdd_mcu_adjust_cycle(&cd->cdd, deduction); |
818 lc8951_adjust_cycles(&cd->cdc, deduction); | |
794 } | 819 } |
795 | 820 |
796 static uint16_t main_gate_read16(uint32_t address, void *vcontext) | 821 static uint16_t main_gate_read16(uint32_t address, void *vcontext) |
797 { | 822 { |
798 m68k_context *m68k = vcontext; | 823 m68k_context *m68k = vcontext; |
826 return cd->rom_mut[0x72/2]; | 851 return cd->rom_mut[0x72/2]; |
827 case GA_CDC_HOST_DATA: { | 852 case GA_CDC_HOST_DATA: { |
828 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; | 853 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; |
829 if (dst == DST_MAIN_CPU) { | 854 if (dst == DST_MAIN_CPU) { |
830 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { | 855 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { |
856 printf("DSR cleared at %u (%u)\n", scd_cycle, cd->cdc.cycle); | |
831 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR; | 857 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR; |
832 lc8951_resume_transfer(&cd->cdc); | 858 lc8951_resume_transfer(&cd->cdc, scd_cycle); |
859 } else { | |
860 printf("Read of CDC host data with DSR clear at %u\n", scd_cycle); | |
833 } | 861 } |
834 calculate_target_cycle(cd->m68k); | 862 calculate_target_cycle(cd->m68k); |
835 return cd->gate_array[offset]; | 863 } |
836 } else { | 864 return cd->gate_array[offset]; |
837 return 0xFFFF; | |
838 } | |
839 } | 865 } |
840 case GA_CDC_DMA_ADDR: | 866 case GA_CDC_DMA_ADDR: |
841 //TODO: open bus maybe? | 867 //TODO: open bus maybe? |
842 return 0xFFFF; | 868 return 0xFFFF; |
843 default: | 869 default: |
844 if (offset < GA_TIMER) { | 870 if (offset < GA_TIMER) { |
871 if (offset == GA_CDC_CTRL) { | |
872 printf("CDC read(main): %X - %X @ %u (%u)\n", address, cd->gate_array[offset], m68k->current_cycle, scd_cycle); | |
873 } else if (offset >= GA_COMM_FLAG && offset <= GA_COMM_STATUS7) { | |
874 printf("COMM read(main): %X - %X @ %u (%u)\n", address, cd->gate_array[offset], m68k->current_cycle, scd_cycle); | |
875 } | |
845 return cd->gate_array[offset]; | 876 return cd->gate_array[offset]; |
846 } | 877 } |
847 //TODO: open bus maybe? | 878 //TODO: open bus maybe? |
848 return 0xFFFF; | 879 return 0xFFFF; |
849 } | 880 } |
927 break; | 958 break; |
928 case GA_COMM_FLAG: | 959 case GA_COMM_FLAG: |
929 //Main CPU can only write the upper byte; | 960 //Main CPU can only write the upper byte; |
930 cd->gate_array[reg] &= 0xFF; | 961 cd->gate_array[reg] &= 0xFF; |
931 cd->gate_array[reg] |= value & 0xFF00; | 962 cd->gate_array[reg] |= value & 0xFF00; |
963 printf("COMM write(main): %X - %X @ %u (%u)\n", address, value, m68k->current_cycle, scd_cycle); | |
932 break; | 964 break; |
933 case GA_COMM_CMD0: | 965 case GA_COMM_CMD0: |
934 case GA_COMM_CMD1: | 966 case GA_COMM_CMD1: |
935 case GA_COMM_CMD2: | 967 case GA_COMM_CMD2: |
936 case GA_COMM_CMD3: | 968 case GA_COMM_CMD3: |
937 case GA_COMM_CMD4: | 969 case GA_COMM_CMD4: |
938 case GA_COMM_CMD5: | 970 case GA_COMM_CMD5: |
939 case GA_COMM_CMD6: | 971 case GA_COMM_CMD6: |
940 case GA_COMM_CMD7: | 972 case GA_COMM_CMD7: |
941 //no effects for these other than saving the value | 973 //no effects for these other than saving the value |
974 printf("COMM write(main): %X - %X @ %u (%u)\n", address, value, m68k->current_cycle, scd_cycle); | |
942 cd->gate_array[reg] = value; | 975 cd->gate_array[reg] = value; |
943 break; | 976 break; |
944 default: | 977 default: |
945 printf("Unhandled gate array write %X:%X\n", address, value); | 978 printf("Unhandled gate array write %X:%X\n", address, value); |
946 } | 979 } |