comparison segacd.c @ 2135:95b3752925e0

Can now pass all CDC DMA3 tests in mcd-verificator
author Michael Pavone <pavone@retrodev.com>
date Fri, 18 Mar 2022 21:55:30 -0700
parents 9caebcfeac72
children 01fcbcba5cf8
comparison
equal deleted inserted replaced
2134:9caebcfeac72 2135:95b3752925e0
738 cdd_run(cd, m68k->current_cycle); 738 cdd_run(cd, m68k->current_cycle);
739 lc8951_ar_write(&cd->cdc, value); 739 lc8951_ar_write(&cd->cdc, value);
740 //cd->gate_array[reg] &= 0xC000; 740 //cd->gate_array[reg] &= 0xC000;
741 //apparently this clears EDT, should it also clear DSR? 741 //apparently this clears EDT, should it also clear DSR?
742 cd->gate_array[reg] = value & 0x0700; 742 cd->gate_array[reg] = value & 0x0700;
743 cd->gate_array[GA_CDC_DMA_ADDR] = 0;
743 cd->cdc_dst_low = 0; 744 cd->cdc_dst_low = 0;
744 break; 745 break;
745 case GA_CDC_REG_DATA: 746 case GA_CDC_REG_DATA:
746 cdd_run(cd, m68k->current_cycle); 747 cdd_run(cd, m68k->current_cycle);
747 printf("CDC write %X: %X @ %u\n", cd->cdc.ar, value, m68k->current_cycle); 748 printf("CDC write %X: %X @ %u\n", cd->cdc.ar, value, m68k->current_cycle);
748 lc8951_reg_write(&cd->cdc, value); 749 lc8951_reg_write(&cd->cdc, value);
749 calculate_target_cycle(m68k); 750 calculate_target_cycle(m68k);
751 break;
752 case GA_CDC_HOST_DATA:
753 //writes to this register have the same side effects as reads
754 sub_gate_read16(address, vcontext);
750 break; 755 break;
751 case GA_CDC_DMA_ADDR: 756 case GA_CDC_DMA_ADDR:
752 cdd_run(cd, m68k->current_cycle); 757 cdd_run(cd, m68k->current_cycle);
753 cd->gate_array[reg] = value; 758 cd->gate_array[reg] = value;
754 cd->cdc_dst_low = 0; 759 cd->cdc_dst_low = 0;
912 } 917 }
913 } 918 }
914 return sub_gate_write16(address, vcontext, value16); 919 return sub_gate_write16(address, vcontext, value16);
915 } 920 }
916 921
922 static uint8_t can_main_access_prog(segacd_context *cd)
923 {
924 //TODO: use actual busack
925 return cd->busreq || !cd->reset;
926 }
927
917 static uint8_t handle_cdc_byte(void *vsys, uint8_t value) 928 static uint8_t handle_cdc_byte(void *vsys, uint8_t value)
918 { 929 {
919 segacd_context *cd = vsys; 930 segacd_context *cd = vsys;
920 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) { 931 if (cd->gate_array[GA_CDC_CTRL] & BIT_DSR) {
921 //host reg is already full, pause transfer 932 //host reg is already full, pause transfer
960 dma_addr += 2; 971 dma_addr += 2;
961 cd->cdc_dst_low = dma_addr & 7; 972 cd->cdc_dst_low = dma_addr & 7;
962 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; 973 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
963 break; 974 break;
964 case DST_PROG_RAM: 975 case DST_PROG_RAM:
976 if (can_main_access_prog(cd)) {
977 return 0;
978 }
965 cd->prog_ram[dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; 979 cd->prog_ram[dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA];
966 m68k_invalidate_code_range(cd->m68k, dma_addr - 1, dma_addr + 1); 980 m68k_invalidate_code_range(cd->m68k, dma_addr - 1, dma_addr + 1);
967 dma_addr++; 981 dma_addr++;
968 cd->cdc_dst_low = dma_addr & 7; 982 cd->cdc_dst_low = dma_addr & 7;
969 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; 983 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
970 break; 984 break;
971 case DST_WORD_RAM: 985 case DST_WORD_RAM:
972 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { 986 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
973 //1M mode, write to bank assigned to Sub CPU 987 //1M mode, write to bank assigned to Sub CPU
974 dma_addr &= (1 << 17) - 2; 988
975 cd->m68k->mem_pointers[1][dma_addr] = cd->gate_array[GA_CDC_HOST_DATA]; 989 uint32_t masked = dma_addr & (1 << 17) - 2;
976 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1); 990 cd->m68k->mem_pointers[1][masked] = cd->gate_array[GA_CDC_HOST_DATA];
991 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + masked - 1, 0x0C0000 + masked + 1);
977 } else { 992 } else {
978 //2M mode, check if Sub CPU has access 993 //2M mode, check if Sub CPU has access
979 if (cd->main_has_word2m) { 994 if (cd->main_has_word2m) {
980 return 0; 995 return 0;
981 } else { 996 } else {
991 break; 1006 break;
992 default: 1007 default:
993 printf("Invalid CDC transfer destination %d\n", dest); 1008 printf("Invalid CDC transfer destination %d\n", dest);
994 } 1009 }
995 return 1; 1010 return 1;
996 }
997
998 static uint8_t can_main_access_prog(segacd_context *cd)
999 {
1000 //TODO: use actual busack
1001 return cd->busreq || !cd->reset;
1002 } 1011 }
1003 1012
1004 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle) 1013 static void scd_peripherals_run(segacd_context *cd, uint32_t cycle)
1005 { 1014 {
1006 timers_run(cd, cycle); 1015 timers_run(cd, cycle);
1223 } 1232 }
1224 } else if (old_access) { 1233 } else if (old_access) {
1225 m68k->mem_pointers[cd->memptr_start_index] = NULL; 1234 m68k->mem_pointers[cd->memptr_start_index] = NULL;
1226 m68k_invalidate_code_range(m68k, cd->base + 0x220000, cd->base + 0x240000); 1235 m68k_invalidate_code_range(m68k, cd->base + 0x220000, cd->base + 0x240000);
1227 m68k_invalidate_code_range(cd->m68k, bank * 0x20000, (bank + 1) * 0x20000); 1236 m68k_invalidate_code_range(cd->m68k, bank * 0x20000, (bank + 1) * 0x20000);
1228 if (!new_access) { 1237 dump_prog_ram(cd);
1229 dump_prog_ram(cd); 1238 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
1239 if (dst == DST_PROG_RAM) {
1240 lc8951_resume_transfer(&cd->cdc, cd->cdc.cycle);
1230 } 1241 }
1231 } 1242 }
1232 break; 1243 break;
1233 } 1244 }
1234 case GA_MEM_MODE: { 1245 case GA_MEM_MODE: {
1273 } 1284 }
1274 break; 1285 break;
1275 } 1286 }
1276 case GA_HINT_VECTOR: 1287 case GA_HINT_VECTOR:
1277 cd->rom_mut[0x72/2] = value; 1288 cd->rom_mut[0x72/2] = value;
1289 break;
1290 case GA_CDC_HOST_DATA:
1291 //writes to this register have the same side effects as reads
1292 main_gate_read16(address, vcontext);
1278 break; 1293 break;
1279 case GA_COMM_FLAG: 1294 case GA_COMM_FLAG:
1280 //Main CPU can only write the upper byte; 1295 //Main CPU can only write the upper byte;
1281 cd->gate_array[reg] &= 0xFF; 1296 cd->gate_array[reg] &= 0xFF;
1282 cd->gate_array[reg] |= value & 0xFF00; 1297 cd->gate_array[reg] |= value & 0xFF00;