Mercurial > repos > blastem
diff 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 |
line wrap: on
line diff
--- a/segacd.c Thu Mar 17 22:41:42 2022 -0700 +++ b/segacd.c Fri Mar 18 20:49:07 2022 -0700 @@ -131,12 +131,11 @@ static uint16_t word_ram_2M_read16(uint32_t address, void *vcontext) { m68k_context *m68k = vcontext; - //TODO: fixme for interleaving uint16_t* bank = m68k->mem_pointers[1]; if (!bank) { return 0xFFFF; } - uint16_t raw = bank[address >> 2]; + uint16_t raw = bank[address >> 1 & ~1]; if (address & 2) { return (raw & 0xF) | (raw << 4 & 0xF00); } else { @@ -157,30 +156,45 @@ { m68k_context *m68k = vcontext; segacd_context *cd = m68k->system; - value &= 0xF; - uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY; + if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) { + if (address & 1) { + address >>= 1; + cd->word_ram[address] &= 0xFF00; + cd->word_ram[address] |= value; + } else { + address >>= 1; + cd->word_ram[address] &= 0x00FF; + cd->word_ram[address] |= value << 8; + } + cd->sub_paused_wordram = 1; + m68k->sync_cycle = m68k->target_cycle = m68k->current_cycle; + m68k->should_return = 1; + } else { + value &= 0xF; + uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY; - if (priority == BIT_OVERWRITE && !value) { - return vcontext; - } - if (priority == BIT_UNDERWRITE) { - if (!value) { + if (priority == BIT_OVERWRITE && !value) { return vcontext; } - uint8_t old = word_ram_2M_read8(address, vcontext); - if (old) { + if (priority == BIT_UNDERWRITE) { + if (!value) { + return vcontext; + } + uint8_t old = word_ram_2M_read8(address, vcontext); + if (old) { + return vcontext; + } + } + uint16_t* bank = m68k->mem_pointers[1]; + if (!bank) { return vcontext; } - } - uint16_t* bank = m68k->mem_pointers[1]; - if (!bank) { - return vcontext; + uint16_t raw = bank[address >> 1 & ~1]; + uint16_t shift = ((address & 3) * 4); + raw &= ~(0xF000 >> shift); + raw |= value << (12 - shift); + bank[address >> 1 & ~1] = raw; } - uint16_t raw = bank[address >> 2]; - uint16_t shift = ((address & 3) * 4); - raw &= ~(0xF000 >> shift); - raw |= value << (12 - shift); - bank[address >> 2] = raw; return vcontext; } @@ -234,21 +248,60 @@ static uint16_t unmapped_word_read16(uint32_t address, void *vcontext) { - return 0xFFFF; + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { + return cd->word_ram[address + cd->bank_toggle]; + } else { + return 0xFFFF; + } } static uint8_t unmapped_word_read8(uint32_t address, void *vcontext) { - return 0xFF; + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { + if (address & 1) { + return cd->word_ram[(address & ~1) + cd->bank_toggle]; + } else { + return cd->word_ram[address + cd->bank_toggle] >> 8; + } + } else { + return 0xFF; + } } static void *unmapped_word_write16(uint32_t address, void *vcontext, uint16_t value) { + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { + cd->word_ram[address + cd->bank_toggle] = value; + m68k_invalidate_code_range(m68k, cd->base + address, address + 1); + } return vcontext; } static void *unmapped_word_write8(uint32_t address, void *vcontext, uint8_t value) { + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { + if (address & 1) { + uint32_t offset = (address & ~1) + cd->bank_toggle; + cd->word_ram[offset] &= 0xFF00; + cd->word_ram[offset] |= value; + } else { + cd->word_ram[address + cd->bank_toggle] &= 0xFF; + cd->word_ram[address + cd->bank_toggle] |= value << 8; + } + m68k_invalidate_code_range(m68k, cd->base + (address & ~1), address + 1); + } return vcontext; } @@ -286,10 +339,10 @@ m68k_context *m68k = vcontext; genesis_context *gen = m68k->system; segacd_context *cd = gen->expansion; - if (!m68k->mem_pointers[cd->memptr_start_index + 1]) { + if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) { return 0xFFFF; } - return m68k->mem_pointers[cd->memptr_start_index + 1][address>>1]; + return cd->word_ram[address + cd->bank_toggle]; } static uint8_t cell_image_read8(uint32_t address, void *vcontext) @@ -303,12 +356,12 @@ static void *cell_image_write16(uint32_t address, void *vcontext, uint16_t value) { - address = cell_image_translate_address(address); m68k_context *m68k = vcontext; genesis_context *gen = m68k->system; segacd_context *cd = gen->expansion; - if (m68k->mem_pointers[cd->memptr_start_index + 1]) { - m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] = value; + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { + address = cell_image_translate_address(address); + cd->word_ram[address + cd->bank_toggle] = value; } return vcontext; } @@ -320,13 +373,13 @@ m68k_context *m68k = vcontext; genesis_context *gen = m68k->system; segacd_context *cd = gen->expansion; - if (m68k->mem_pointers[cd->memptr_start_index + 1]) { + if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { if (byte) { - m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0xFF00; - m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value; + cd->word_ram[address + cd->bank_toggle] &= 0xFF00; + cd->word_ram[address + cd->bank_toggle] |= value; } else { - m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0x00FF; - m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value << 8; + cd->word_ram[address + cd->bank_toggle] &= 0x00FF; + cd->word_ram[address + cd->bank_toggle] |= value << 8; } } return vcontext; @@ -624,14 +677,13 @@ genesis_context *gen = cd->genesis; cd->gate_array[reg] &= 0xFFC0; if (changed & BIT_MEM_MODE) { - //FIXME: ram banks are supposed to be interleaved when in 2M mode cd->main_swap_request = cd->bank_toggle && !old_bank_toggle; if (value & BIT_MEM_MODE) { //switch to 1M mode - gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram; + gen->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL; //(value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram; gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL; m68k->mem_pointers[0] = NULL; - m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 0x10000; + m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 1; cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE); if (cd->main_swap_request) { cd->gate_array[reg] |= BIT_DMNA; @@ -659,8 +711,7 @@ } else if (value & BIT_MEM_MODE) { //1M mode if (old_bank_toggle != cd->bank_toggle) { - gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram; - m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 0x10000; + m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 1; m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000); m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000); cd->main_swap_request = 0; @@ -920,8 +971,8 @@ case DST_WORD_RAM: if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { //1M mode, write to bank assigned to Sub CPU - dma_addr &= (1 << 17) - 1; - cd->m68k->mem_pointers[1][dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA]; + dma_addr &= (1 << 17) - 2; + cd->m68k->mem_pointers[1][dma_addr] = cd->gate_array[GA_CDC_HOST_DATA]; m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1); } else { //2M mode, check if Sub CPU has access @@ -1001,7 +1052,7 @@ { uint8_t m68k_run = !can_main_access_prog(cd); while (cycle > cd->m68k->current_cycle) { - if (m68k_run) { + if (m68k_run && !cd->sub_paused_wordram) { uint32_t start = cd->m68k->current_cycle; cd->m68k->sync_cycle = cd->enter_debugger ? cd->m68k->current_cycle + 1 : cycle; if (cd->need_reset) { @@ -1202,6 +1253,9 @@ cd->m68k->mem_pointers[0] = cd->word_ram; cd->gate_array[reg] &= ~BIT_RET; cd->main_has_word2m = 0; + if (cd->sub_paused_wordram) { + cd->sub_paused_wordram = 0; + } uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7; if (dst == DST_WORD_RAM) { @@ -1289,7 +1343,7 @@ {0x080000, 0x0C0000, 0x03FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 0, .read_16 = word_ram_2M_read16, .write_16 = word_ram_2M_write16, .read_8 = word_ram_2M_read8, .write_8 = word_ram_2M_write8}, {0x0C0000, 0x0E0000, 0x01FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1, - .read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8}, + .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}, {0xFE0000, 0xFF0000, 0x003FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD}, {0xFF0000, 0xFF8000, 0x003FFF, .read_16 = pcm_read16, .write_16 = pcm_write16, .read_8 = pcm_read8, .write_8 = pcm_write8}, {0xFF8000, 0xFF8200, 0x0001FF, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8}