comparison segacd.c @ 2134:9caebcfeac72

Implement word RAM interleaving in 1M mode, now passes mcd-verificator word RAM tests
author Michael Pavone <pavone@retrodev.com>
date Fri, 18 Mar 2022 20:49:07 -0700
parents d90d92ce5cab
children 95b3752925e0
comparison
equal deleted inserted replaced
2133:8554751f17b5 2134:9caebcfeac72
129 } 129 }
130 130
131 static uint16_t word_ram_2M_read16(uint32_t address, void *vcontext) 131 static uint16_t word_ram_2M_read16(uint32_t address, void *vcontext)
132 { 132 {
133 m68k_context *m68k = vcontext; 133 m68k_context *m68k = vcontext;
134 //TODO: fixme for interleaving
135 uint16_t* bank = m68k->mem_pointers[1]; 134 uint16_t* bank = m68k->mem_pointers[1];
136 if (!bank) { 135 if (!bank) {
137 return 0xFFFF; 136 return 0xFFFF;
138 } 137 }
139 uint16_t raw = bank[address >> 2]; 138 uint16_t raw = bank[address >> 1 & ~1];
140 if (address & 2) { 139 if (address & 2) {
141 return (raw & 0xF) | (raw << 4 & 0xF00); 140 return (raw & 0xF) | (raw << 4 & 0xF00);
142 } else { 141 } else {
143 return (raw >> 4 & 0xF00) | (raw >> 8 & 0xF); 142 return (raw >> 4 & 0xF00) | (raw >> 8 & 0xF);
144 } 143 }
155 154
156 static void *word_ram_2M_write8(uint32_t address, void *vcontext, uint8_t value) 155 static void *word_ram_2M_write8(uint32_t address, void *vcontext, uint8_t value)
157 { 156 {
158 m68k_context *m68k = vcontext; 157 m68k_context *m68k = vcontext;
159 segacd_context *cd = m68k->system; 158 segacd_context *cd = m68k->system;
160 value &= 0xF; 159 if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) {
161 uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY; 160 if (address & 1) {
162 161 address >>= 1;
163 if (priority == BIT_OVERWRITE && !value) { 162 cd->word_ram[address] &= 0xFF00;
164 return vcontext; 163 cd->word_ram[address] |= value;
165 } 164 } else {
166 if (priority == BIT_UNDERWRITE) { 165 address >>= 1;
167 if (!value) { 166 cd->word_ram[address] &= 0x00FF;
167 cd->word_ram[address] |= value << 8;
168 }
169 cd->sub_paused_wordram = 1;
170 m68k->sync_cycle = m68k->target_cycle = m68k->current_cycle;
171 m68k->should_return = 1;
172 } else {
173 value &= 0xF;
174 uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY;
175
176 if (priority == BIT_OVERWRITE && !value) {
168 return vcontext; 177 return vcontext;
169 } 178 }
170 uint8_t old = word_ram_2M_read8(address, vcontext); 179 if (priority == BIT_UNDERWRITE) {
171 if (old) { 180 if (!value) {
181 return vcontext;
182 }
183 uint8_t old = word_ram_2M_read8(address, vcontext);
184 if (old) {
185 return vcontext;
186 }
187 }
188 uint16_t* bank = m68k->mem_pointers[1];
189 if (!bank) {
172 return vcontext; 190 return vcontext;
173 } 191 }
174 } 192 uint16_t raw = bank[address >> 1 & ~1];
175 uint16_t* bank = m68k->mem_pointers[1]; 193 uint16_t shift = ((address & 3) * 4);
176 if (!bank) { 194 raw &= ~(0xF000 >> shift);
177 return vcontext; 195 raw |= value << (12 - shift);
178 } 196 bank[address >> 1 & ~1] = raw;
179 uint16_t raw = bank[address >> 2]; 197 }
180 uint16_t shift = ((address & 3) * 4);
181 raw &= ~(0xF000 >> shift);
182 raw |= value << (12 - shift);
183 bank[address >> 2] = raw;
184 return vcontext; 198 return vcontext;
185 } 199 }
186 200
187 201
188 static void *word_ram_2M_write16(uint32_t address, void *vcontext, uint16_t value) 202 static void *word_ram_2M_write16(uint32_t address, void *vcontext, uint16_t value)
232 return vcontext; 246 return vcontext;
233 } 247 }
234 248
235 static uint16_t unmapped_word_read16(uint32_t address, void *vcontext) 249 static uint16_t unmapped_word_read16(uint32_t address, void *vcontext)
236 { 250 {
237 return 0xFFFF; 251 m68k_context *m68k = vcontext;
252 genesis_context *gen = m68k->system;
253 segacd_context *cd = gen->expansion;
254 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
255 return cd->word_ram[address + cd->bank_toggle];
256 } else {
257 return 0xFFFF;
258 }
238 } 259 }
239 260
240 static uint8_t unmapped_word_read8(uint32_t address, void *vcontext) 261 static uint8_t unmapped_word_read8(uint32_t address, void *vcontext)
241 { 262 {
242 return 0xFF; 263 m68k_context *m68k = vcontext;
264 genesis_context *gen = m68k->system;
265 segacd_context *cd = gen->expansion;
266 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
267 if (address & 1) {
268 return cd->word_ram[(address & ~1) + cd->bank_toggle];
269 } else {
270 return cd->word_ram[address + cd->bank_toggle] >> 8;
271 }
272 } else {
273 return 0xFF;
274 }
243 } 275 }
244 276
245 static void *unmapped_word_write16(uint32_t address, void *vcontext, uint16_t value) 277 static void *unmapped_word_write16(uint32_t address, void *vcontext, uint16_t value)
246 { 278 {
279 m68k_context *m68k = vcontext;
280 genesis_context *gen = m68k->system;
281 segacd_context *cd = gen->expansion;
282 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
283 cd->word_ram[address + cd->bank_toggle] = value;
284 m68k_invalidate_code_range(m68k, cd->base + address, address + 1);
285 }
247 return vcontext; 286 return vcontext;
248 } 287 }
249 288
250 static void *unmapped_word_write8(uint32_t address, void *vcontext, uint8_t value) 289 static void *unmapped_word_write8(uint32_t address, void *vcontext, uint8_t value)
251 { 290 {
291 m68k_context *m68k = vcontext;
292 genesis_context *gen = m68k->system;
293 segacd_context *cd = gen->expansion;
294 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
295 if (address & 1) {
296 uint32_t offset = (address & ~1) + cd->bank_toggle;
297 cd->word_ram[offset] &= 0xFF00;
298 cd->word_ram[offset] |= value;
299 } else {
300 cd->word_ram[address + cd->bank_toggle] &= 0xFF;
301 cd->word_ram[address + cd->bank_toggle] |= value << 8;
302 }
303 m68k_invalidate_code_range(m68k, cd->base + (address & ~1), address + 1);
304 }
252 return vcontext; 305 return vcontext;
253 } 306 }
254 307
255 static uint32_t cell_image_translate_address(uint32_t address) 308 static uint32_t cell_image_translate_address(uint32_t address)
256 { 309 {
284 { 337 {
285 address = cell_image_translate_address(address); 338 address = cell_image_translate_address(address);
286 m68k_context *m68k = vcontext; 339 m68k_context *m68k = vcontext;
287 genesis_context *gen = m68k->system; 340 genesis_context *gen = m68k->system;
288 segacd_context *cd = gen->expansion; 341 segacd_context *cd = gen->expansion;
289 if (!m68k->mem_pointers[cd->memptr_start_index + 1]) { 342 if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) {
290 return 0xFFFF; 343 return 0xFFFF;
291 } 344 }
292 return m68k->mem_pointers[cd->memptr_start_index + 1][address>>1]; 345 return cd->word_ram[address + cd->bank_toggle];
293 } 346 }
294 347
295 static uint8_t cell_image_read8(uint32_t address, void *vcontext) 348 static uint8_t cell_image_read8(uint32_t address, void *vcontext)
296 { 349 {
297 uint16_t word = cell_image_read16(address & 0xFFFFFE, vcontext); 350 uint16_t word = cell_image_read16(address & 0xFFFFFE, vcontext);
301 return word >> 8; 354 return word >> 8;
302 } 355 }
303 356
304 static void *cell_image_write16(uint32_t address, void *vcontext, uint16_t value) 357 static void *cell_image_write16(uint32_t address, void *vcontext, uint16_t value)
305 { 358 {
306 address = cell_image_translate_address(address);
307 m68k_context *m68k = vcontext; 359 m68k_context *m68k = vcontext;
308 genesis_context *gen = m68k->system; 360 genesis_context *gen = m68k->system;
309 segacd_context *cd = gen->expansion; 361 segacd_context *cd = gen->expansion;
310 if (m68k->mem_pointers[cd->memptr_start_index + 1]) { 362 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
311 m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] = value; 363 address = cell_image_translate_address(address);
364 cd->word_ram[address + cd->bank_toggle] = value;
312 } 365 }
313 return vcontext; 366 return vcontext;
314 } 367 }
315 368
316 static void *cell_image_write8(uint32_t address, void *vcontext, uint8_t value) 369 static void *cell_image_write8(uint32_t address, void *vcontext, uint8_t value)
318 uint32_t byte = address & 1; 371 uint32_t byte = address & 1;
319 address = cell_image_translate_address(address); 372 address = cell_image_translate_address(address);
320 m68k_context *m68k = vcontext; 373 m68k_context *m68k = vcontext;
321 genesis_context *gen = m68k->system; 374 genesis_context *gen = m68k->system;
322 segacd_context *cd = gen->expansion; 375 segacd_context *cd = gen->expansion;
323 if (m68k->mem_pointers[cd->memptr_start_index + 1]) { 376 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
324 if (byte) { 377 if (byte) {
325 m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0xFF00; 378 cd->word_ram[address + cd->bank_toggle] &= 0xFF00;
326 m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value; 379 cd->word_ram[address + cd->bank_toggle] |= value;
327 } else { 380 } else {
328 m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0x00FF; 381 cd->word_ram[address + cd->bank_toggle] &= 0x00FF;
329 m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value << 8; 382 cd->word_ram[address + cd->bank_toggle] |= value << 8;
330 } 383 }
331 } 384 }
332 return vcontext; 385 return vcontext;
333 } 386 }
334 387
622 uint8_t old_bank_toggle = cd->bank_toggle; 675 uint8_t old_bank_toggle = cd->bank_toggle;
623 cd->bank_toggle = value & BIT_RET; 676 cd->bank_toggle = value & BIT_RET;
624 genesis_context *gen = cd->genesis; 677 genesis_context *gen = cd->genesis;
625 cd->gate_array[reg] &= 0xFFC0; 678 cd->gate_array[reg] &= 0xFFC0;
626 if (changed & BIT_MEM_MODE) { 679 if (changed & BIT_MEM_MODE) {
627 //FIXME: ram banks are supposed to be interleaved when in 2M mode
628 cd->main_swap_request = cd->bank_toggle && !old_bank_toggle; 680 cd->main_swap_request = cd->bank_toggle && !old_bank_toggle;
629 if (value & BIT_MEM_MODE) { 681 if (value & BIT_MEM_MODE) {
630 //switch to 1M mode 682 //switch to 1M mode
631 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram; 683 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL; //(value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
632 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL; 684 gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
633 m68k->mem_pointers[0] = NULL; 685 m68k->mem_pointers[0] = NULL;
634 m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 0x10000; 686 m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 1;
635 cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE); 687 cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE);
636 if (cd->main_swap_request) { 688 if (cd->main_swap_request) {
637 cd->gate_array[reg] |= BIT_DMNA; 689 cd->gate_array[reg] |= BIT_DMNA;
638 } 690 }
639 } else { 691 } else {
657 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000); 709 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
658 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000); 710 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
659 } else if (value & BIT_MEM_MODE) { 711 } else if (value & BIT_MEM_MODE) {
660 //1M mode 712 //1M mode
661 if (old_bank_toggle != cd->bank_toggle) { 713 if (old_bank_toggle != cd->bank_toggle) {
662 gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram; 714 m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 1;
663 m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 0x10000;
664 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000); 715 m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
665 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000); 716 m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
666 cd->main_swap_request = 0; 717 cd->main_swap_request = 0;
667 } 718 }
668 cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE); 719 cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE);
918 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3; 969 cd->gate_array[GA_CDC_DMA_ADDR] = dma_addr >> 3;
919 break; 970 break;
920 case DST_WORD_RAM: 971 case DST_WORD_RAM:
921 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { 972 if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
922 //1M mode, write to bank assigned to Sub CPU 973 //1M mode, write to bank assigned to Sub CPU
923 dma_addr &= (1 << 17) - 1; 974 dma_addr &= (1 << 17) - 2;
924 cd->m68k->mem_pointers[1][dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; 975 cd->m68k->mem_pointers[1][dma_addr] = cd->gate_array[GA_CDC_HOST_DATA];
925 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1); 976 m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1);
926 } else { 977 } else {
927 //2M mode, check if Sub CPU has access 978 //2M mode, check if Sub CPU has access
928 if (cd->main_has_word2m) { 979 if (cd->main_has_word2m) {
929 return 0; 980 return 0;
999 1050
1000 void scd_run(segacd_context *cd, uint32_t cycle) 1051 void scd_run(segacd_context *cd, uint32_t cycle)
1001 { 1052 {
1002 uint8_t m68k_run = !can_main_access_prog(cd); 1053 uint8_t m68k_run = !can_main_access_prog(cd);
1003 while (cycle > cd->m68k->current_cycle) { 1054 while (cycle > cd->m68k->current_cycle) {
1004 if (m68k_run) { 1055 if (m68k_run && !cd->sub_paused_wordram) {
1005 uint32_t start = cd->m68k->current_cycle; 1056 uint32_t start = cd->m68k->current_cycle;
1006 cd->m68k->sync_cycle = cd->enter_debugger ? cd->m68k->current_cycle + 1 : cycle; 1057 cd->m68k->sync_cycle = cd->enter_debugger ? cd->m68k->current_cycle + 1 : cycle;
1007 if (cd->need_reset) { 1058 if (cd->need_reset) {
1008 cd->need_reset = 0; 1059 cd->need_reset = 0;
1009 m68k_reset(cd->m68k); 1060 m68k_reset(cd->m68k);
1200 m68k->mem_pointers[cd->memptr_start_index + 1] = NULL; 1251 m68k->mem_pointers[cd->memptr_start_index + 1] = NULL;
1201 m68k->mem_pointers[cd->memptr_start_index + 2] = NULL; 1252 m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
1202 cd->m68k->mem_pointers[0] = cd->word_ram; 1253 cd->m68k->mem_pointers[0] = cd->word_ram;
1203 cd->gate_array[reg] &= ~BIT_RET; 1254 cd->gate_array[reg] &= ~BIT_RET;
1204 cd->main_has_word2m = 0; 1255 cd->main_has_word2m = 0;
1256 if (cd->sub_paused_wordram) {
1257 cd->sub_paused_wordram = 0;
1258 }
1205 1259
1206 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; 1260 uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
1207 if (dst == DST_WORD_RAM) { 1261 if (dst == DST_WORD_RAM) {
1208 lc8951_resume_transfer(&cd->cdc, cd->cdc.cycle); 1262 lc8951_resume_transfer(&cd->cdc, cd->cdc.cycle);
1209 } 1263 }
1287 {0x000000, 0x01FF00, 0xFFFFFF, .flags=MMAP_READ | MMAP_CODE, .write_16 = prog_ram_wp_write16, .write_8 = prog_ram_wp_write8}, 1341 {0x000000, 0x01FF00, 0xFFFFFF, .flags=MMAP_READ | MMAP_CODE, .write_16 = prog_ram_wp_write16, .write_8 = prog_ram_wp_write8},
1288 {0x01FF00, 0x080000, 0xFFFFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE}, 1342 {0x01FF00, 0x080000, 0xFFFFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE},
1289 {0x080000, 0x0C0000, 0x03FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 0, 1343 {0x080000, 0x0C0000, 0x03FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 0,
1290 .read_16 = word_ram_2M_read16, .write_16 = word_ram_2M_write16, .read_8 = word_ram_2M_read8, .write_8 = word_ram_2M_write8}, 1344 .read_16 = word_ram_2M_read16, .write_16 = word_ram_2M_write16, .read_8 = word_ram_2M_read8, .write_8 = word_ram_2M_write8},
1291 {0x0C0000, 0x0E0000, 0x01FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1, 1345 {0x0C0000, 0x0E0000, 0x01FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1,
1292 .read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8}, 1346 .read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8, .shift = 1},
1293 {0xFE0000, 0xFF0000, 0x003FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD}, 1347 {0xFE0000, 0xFF0000, 0x003FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD},
1294 {0xFF0000, 0xFF8000, 0x003FFF, .read_16 = pcm_read16, .write_16 = pcm_write16, .read_8 = pcm_read8, .write_8 = pcm_write8}, 1348 {0xFF0000, 0xFF8000, 0x003FFF, .read_16 = pcm_read16, .write_16 = pcm_write16, .read_8 = pcm_read8, .write_8 = pcm_write8},
1295 {0xFF8000, 0xFF8200, 0x0001FF, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8} 1349 {0xFF8000, 0xFF8200, 0x0001FF, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8}
1296 }; 1350 };
1297 1351