comparison segacd.c @ 2065:02a9846668d1 segacd

Implement transfer of data from CDC to elsewhere. Other miscellaneous CDD/CDC improvements
author Michael Pavone <pavone@retrodev.com>
date Sat, 29 Jan 2022 17:43:37 -0800
parents 07ed42bd7b4c
children a61a8a87410c
comparison
equal deleted inserted replaced
2064:91e4d2fe5cd9 2065:02a9846668d1
71 #define MASK_PRIORITY (BIT_OVERWRITE|BIT_UNDERWRITE) 71 #define MASK_PRIORITY (BIT_OVERWRITE|BIT_UNDERWRITE)
72 #define BIT_MEM_MODE 0x0004 72 #define BIT_MEM_MODE 0x0004
73 #define BIT_DMNA 0x0002 73 #define BIT_DMNA 0x0002
74 #define BIT_RET 0x0001 74 #define BIT_RET 0x0001
75 75
76 //GA_CDC_CTRL
77 #define BIT_EDT 0x8000
78 #define BIT_DSR 0x4000
79
80 enum {
81 DST_MAIN_CPU = 2,
82 DST_SUB_CPU,
83 DST_PCM_RAM,
84 DST_PROG_RAM,
85 DST_WORD_RAM = 7
86 };
87
76 //GA_INT_MASK 88 //GA_INT_MASK
77 #define BIT_MASK_IEN1 0x0002 89 #define BIT_MASK_IEN1 0x0002
78 #define BIT_MASK_IEN2 0x0004 90 #define BIT_MASK_IEN2 0x0004
79 #define BIT_MASK_IEN3 0x0008 91 #define BIT_MASK_IEN3 0x0008
80 #define BIT_MASK_IEN4 0x0010 92 #define BIT_MASK_IEN4 0x0010
381 return value; 393 return value;
382 } 394 }
383 case GA_MEM_MODE: 395 case GA_MEM_MODE:
384 return cd->gate_array[reg] & 0xFF1F; 396 return cd->gate_array[reg] & 0xFF1F;
385 case GA_CDC_CTRL: 397 case GA_CDC_CTRL:
398 cdd_run(cd, m68k->current_cycle);
386 return cd->gate_array[reg] | cd->cdc.ar; 399 return cd->gate_array[reg] | cd->cdc.ar;
387 case GA_CDC_REG_DATA: 400 case GA_CDC_REG_DATA:
388 cdd_run(cd, m68k->current_cycle); 401 cdd_run(cd, m68k->current_cycle);
389 return lc8951_reg_read(&cd->cdc); 402 return lc8951_reg_read(&cd->cdc);
403 case GA_CDC_HOST_DATA: {
404 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
405 if (dst == DST_SUB_CPU) {
406 cdd_run(cd, m68k->current_cycle);
407 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) {
408 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR;
409 lc8951_resume_transfer(&cd->cdc);
410 }
411 calculate_target_cycle(cd->m68k);
412 return cd->gate_array[reg];
413 } else {
414 return 0xFFFF;
415 }
416 }
390 case GA_STOP_WATCH: 417 case GA_STOP_WATCH:
391 case GA_TIMER: 418 case GA_TIMER:
392 timers_run(cd, m68k->current_cycle); 419 timers_run(cd, m68k->current_cycle);
393 return cd->gate_array[reg]; 420 return cd->gate_array[reg];
394 case GA_CDD_STATUS0: 421 case GA_CDD_STATUS0:
506 case GA_CDC_REG_DATA: 533 case GA_CDC_REG_DATA:
507 cdd_run(cd, m68k->current_cycle); 534 cdd_run(cd, m68k->current_cycle);
508 lc8951_reg_write(&cd->cdc, value); 535 lc8951_reg_write(&cd->cdc, value);
509 calculate_target_cycle(m68k); 536 calculate_target_cycle(m68k);
510 break; 537 break;
538 case GA_CDC_DMA_ADDR:
539 cdd_run(cd, m68k->current_cycle);
540 cd->gate_array[reg] = value;
541 cd->cdc_dst_low = 0;
542 break;
511 case GA_STOP_WATCH: 543 case GA_STOP_WATCH:
512 //docs say you should only write zero to reset 544 //docs say you should only write zero to reset
513 //mcd-verificator comments suggest any value will reset 545 //mcd-verificator comments suggest any value will reset
514 timers_run(cd, m68k->current_cycle); 546 timers_run(cd, m68k->current_cycle);
515 cd->gate_array[reg] = 0; 547 cd->gate_array[reg] = 0;
619 } 651 }
620 } 652 }
621 return sub_gate_write16(address, vcontext, value16); 653 return sub_gate_write16(address, vcontext, value16);
622 } 654 }
623 655
656 static uint8_t handle_cdc_byte(void *vsys, uint8_t value)
657 {
658 segacd_context *cd = vsys;
659 uint16_t dest = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
660 uint32_t dma_addr = cd->gate_array[GA_CDC_DMA_ADDR] << 3;
661 dma_addr |= cd->cdc_dst_low;
662 switch (dest)
663 {
664 case DST_MAIN_CPU:
665 case DST_SUB_CPU:
666 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) {
667 //host reg is already full, pause transfer
668 return 0;
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;
682 case DST_PCM_RAM:
683 dma_addr &= (1 << 13) - 1;
684 //TODO: write to currently visible 8K bank of PCM RAM I guess?
685 dma_addr++;
686 cd->cdc_dst_low = dma_addr & 7;
687 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
688 break;
689 case DST_PROG_RAM:
690 ((uint8_t*)cd->prog_ram)[dma_addr ^ 1] = value;
691 m68k_invalidate_code_range(cd->m68k, dma_addr, dma_addr + 1);
692 dma_addr++;
693 cd->cdc_dst_low = dma_addr & 7;
694 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
695 break;
696 case DST_WORD_RAM:
697 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
698 //1M mode, write to bank assigned to Sub CPU
699 dma_addr &= (1 << 17) - 1;
700 ((uint8_t*)cd->m68k->mem_pointers[1])[dma_addr ^ 1] = value;
701 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr, 0x0C0000 + dma_addr + 1);
702 } else {
703 //2M mode, check if Sub CPU has access
704 if (!(cd->gate_array[GA_MEM_MODE] & BIT_RET)) {
705 dma_addr &= (1 << 18) - 1;
706 ((uint8_t*)cd->word_ram)[dma_addr ^ 1] = value;
707 m68k_invalidate_code_range(cd->m68k, 0x080000 + dma_addr, 0x080000 + dma_addr + 1);
708 }
709 }
710 dma_addr++;
711 cd->cdc_dst_low = dma_addr & 7;
712 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
713 break;
714 default:
715 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 }
720 return 1;
721 }
722
624 static uint8_t can_main_access_prog(segacd_context *cd) 723 static uint8_t can_main_access_prog(segacd_context *cd)
625 { 724 {
626 //TODO: use actual busack 725 //TODO: use actual busack
627 return cd->busreq || !cd->reset; 726 return cd->busreq || !cd->reset;
628 } 727 }
723 case GA_MEM_MODE: 822 case GA_MEM_MODE:
724 //Main CPU can't read priority mode bits 823 //Main CPU can't read priority mode bits
725 return cd->gate_array[offset] & 0xFFE7; 824 return cd->gate_array[offset] & 0xFFE7;
726 case GA_HINT_VECTOR: 825 case GA_HINT_VECTOR:
727 return cd->rom_mut[0x72/2]; 826 return cd->rom_mut[0x72/2];
827 case GA_CDC_HOST_DATA: {
828 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
829 if (dst == DST_MAIN_CPU) {
830 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) {
831 cd->gate_array[GA_CDC_CTRL] &= ~BIT_DSR;
832 lc8951_resume_transfer(&cd->cdc);
833 }
834 calculate_target_cycle(cd->m68k);
835 return cd->gate_array[offset];
836 } else {
837 return 0xFFFF;
838 }
839 }
728 case GA_CDC_DMA_ADDR: 840 case GA_CDC_DMA_ADDR:
729 //TODO: open bus maybe? 841 //TODO: open bus maybe?
730 return 0xFFFF; 842 return 0xFFFF;
731 default: 843 default:
732 if (offset < GA_TIMER) { 844 if (offset < GA_TIMER) {
925 cd->need_reset = 1; 1037 cd->need_reset = 1;
926 cd->reset = 1; //active low, so reset is not active on start 1038 cd->reset = 1; //active low, so reset is not active on start
927 cd->memptr_start_index = 0; 1039 cd->memptr_start_index = 0;
928 cd->gate_array[1] = 1; 1040 cd->gate_array[1] = 1;
929 cd->gate_array[0x1B] = 0x100; 1041 cd->gate_array[0x1B] = 0x100;
930 lc8951_init(&cd->cdc); 1042 lc8951_init(&cd->cdc, handle_cdc_byte, cd);
931 if (media->chain && media->type != MEDIA_CDROM) { 1043 if (media->chain && media->type != MEDIA_CDROM) {
932 media = media->chain; 1044 media = media->chain;
933 } 1045 }
934 cdd_mcu_init(&cd->cdd, media); 1046 cdd_mcu_init(&cd->cdd, media);
935 1047