# HG changeset patch # User Michael Pavone # Date 1673249428 28800 # Node ID b9fed07f19e4cc601d5af93073e77abbeff6cf51 # Parent 9ead0fe69d9b193ad8150a03f7ad23db8068d635 Implement BRAM cart support diff -r 9ead0fe69d9b -r b9fed07f19e4 genesis.c --- a/genesis.c Sun Jan 08 14:42:24 2023 -0800 +++ b/genesis.c Sun Jan 08 23:30:28 2023 -0800 @@ -1542,6 +1542,17 @@ printf("Saved internal BRAM to %s\n", bram_name); } free(bram_name); + if (cd->bram_cart_id < 8) { + bram_name = path_append(system->save_dir, "cart.bram"); + f = fopen(bram_name, "wb"); + if (f) { + long configured_size = 0x2000 << cd->bram_cart_id; + fwrite(cd->bram_cart, 1, configured_size, f); + fclose(f); + printf("Saved BRAM cart to %s\n", bram_name); + } + free(bram_name); + } } if (gen->save_type == SAVE_NONE) { return; @@ -1588,6 +1599,31 @@ } } free(bram_name); + bram_name = path_append(system->save_dir, "cart.bram"); + f = fopen(bram_name, "rb"); + if (f) { + long existing_size = nearest_pow2(file_size(f)); + if (existing_size > 1 * 1024 * 1024) { + existing_size = 1 * 1024 * 1024; + } + long configured_size = 0x2000 << cd->bram_cart_id; + if (existing_size != configured_size) { + if (existing_size > configured_size) { + free(cd->bram_cart); + cd->bram_cart = calloc(existing_size, 1); + } + cd->bram_cart_id = 0; + while (existing_size > (0x2000 <bram_cart_id)) { + cd->bram_cart_id++; + } + } + uint32_t read = fread(cd->bram_cart, 1, existing_size, f); + fclose(f); + if (read > 0) { + printf("Loaded BRAM cart from %s\n", bram_name); + } + } + free(bram_name); } } diff -r 9ead0fe69d9b -r b9fed07f19e4 segacd.c --- a/segacd.c Sun Jan 08 14:42:24 2023 -0800 +++ b/segacd.c Sun Jan 08 23:30:28 2023 -0800 @@ -440,6 +440,80 @@ return pcm_write8(address+1, vcontext, value); } +static uint16_t cart_area_read16(uint32_t address, void *vcontext) +{ + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + uint16_t open_bus = read_word(m68k->last_prefetch_address, (void **)m68k->mem_pointers, &m68k->options->gen, m68k); + if (cd->bram_cart_id > 7) { + // No cart, just return open bus + return open_bus; + } + address &= 0x3FFFFF; + if (address < 0x200000) { + if (address < 0x100000) { + return (open_bus & 0xFF00) | cd->bram_cart_id; + } + return open_bus; + } else { + address &= 0x1FFFFF; + uint32_t end = 0x2000 << (1 + cd->bram_cart_id); + if (address >= end) { + return open_bus; + } + return (open_bus & 0xFF00) | cd->bram_cart[address >> 1]; + } +} + +static uint8_t cart_area_read8(uint32_t address, void *vcontext) +{ + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (!(address & 1) || cd->bram_cart_id > 7) { + //open bus + return read_byte(m68k->last_prefetch_address | (address & 1), (void **)m68k->mem_pointers, &m68k->options->gen, m68k); + } + address &= 0x3FFFFF; + if (address < 0x200000) { + if (address < 0x100000) { + return cd->bram_cart_id; + } + return read_byte(m68k->last_prefetch_address | 1, (void **)m68k->mem_pointers, &m68k->options->gen, m68k); + } else { + address &= 0x1FFFFF; + uint32_t end = 0x2000 << (1 + cd->bram_cart_id); + if (address >= end) { + return read_byte(m68k->last_prefetch_address | 1, (void **)m68k->mem_pointers, &m68k->options->gen, m68k); + } + return cd->bram_cart[address >> 1]; + } +} + +static void *cart_area_write8(uint32_t address, void *vcontext, uint8_t value) +{ + m68k_context *m68k = vcontext; + genesis_context *gen = m68k->system; + segacd_context *cd = gen->expansion; + if (!(address & 1) || cd->bram_cart_id > 7 || address < 0x600000) { + return vcontext; + } + address &= 0x1FFFFF; + uint32_t end = 0x2000 << (1 + cd->bram_cart_id); + if (address < end && cd->bram_cart_write_enabled) { + cd->bram_cart[address >> 1] = value; + } + if (address == 0x1FFFFF || (cd->bram_cart_id < 7 && address > 0x100000)) { + cd->bram_cart_write_enabled = value & 1; + } + return vcontext; +} + +static void *cart_area_write16(uint32_t address, void *vcontext, uint16_t value) +{ + return cart_area_write8(address | 1, vcontext, value); +} static void timers_run(segacd_context *cd, uint32_t cycle) { @@ -1460,7 +1534,17 @@ cd->prog_ram = calloc(512*1024, 1); cd->word_ram = calloc(256*1024, 1); cd->bram = calloc(8*1024, 1); - + char *bram_size_id = tern_find_path_default(config, "system\0bram_cart_size_id\0", (tern_val){.ptrval = "4"}, TVAL_PTR).ptrval; + cd->bram_cart_id = 0xFF; + cd->bram_cart = NULL; + if (strcmp(bram_size_id, "none")) { + char *end; + long id = strtol(bram_size_id, &end, 10); + if (end != bram_size_id && id < 8) { + cd->bram_cart_id = id; + cd->bram_cart = calloc(0x2000 << id, 1); + } + } sub_cpu_map[0].buffer = sub_cpu_map[1].buffer = cd->prog_ram; sub_cpu_map[4].buffer = cd->bram; @@ -1538,6 +1622,7 @@ save_int8(buf, cd->main_swap_request); save_int8(buf, cd->bank_toggle); save_int8(buf, cd->sub_paused_wordram); + save_int8(buf, cd->bram_cart_write_enabled); end_section(buf); start_section(buf, SECTION_CDD_MCU); @@ -1594,6 +1679,7 @@ cd->main_swap_request = load_int8(buf); cd->bank_toggle = load_int8(buf); cd->sub_paused_wordram = load_int8(buf); + cd->bram_cart_write_enabled = load_int8(buf); if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) { //1M mode @@ -1645,11 +1731,16 @@ .read_16 = unmapped_word_read16, .write_16 = unmapped_word_write16, .read_8 = unmapped_word_read8, .write_8 = unmapped_word_write8}, {0x220000, 0x240000, 0x01FFFF, .flags=MMAP_READ|MMAP_WRITE|MMAP_PTR_IDX|MMAP_FUNC_NULL|MMAP_CODE, .ptr_index = 2, .read_16 = cell_image_read16, .write_16 = cell_image_write16, .read_8 = cell_image_read8, .write_8 = cell_image_write8}, - {0xA12000, 0xA13000, 0xFFFFFF, .read_16 = main_gate_read16, .write_16 = main_gate_write16, .read_8 = main_gate_read8, .write_8 = main_gate_write8} + {0xA12000, 0xA13000, 0xFFFFFF, .read_16 = main_gate_read16, .write_16 = main_gate_write16, .read_8 = main_gate_read8, .write_8 = main_gate_write8}, + {0x400000, 0x800000, 0xFFFFFF, .read_16 = cart_area_read16, .write_16 = cart_area_write16, .read_8 = cart_area_read8, .write_8 = cart_area_write8} }; - for (int i = 0; i < sizeof(main_cpu_map) / sizeof(*main_cpu_map); i++) + *num_chunks = sizeof(main_cpu_map) / sizeof(*main_cpu_map); + if (cart_boot) { + *num_chunks--; + } + for (int i = 0; i < *num_chunks; i++) { - if (main_cpu_map[i].start < 0x800000) { + if (main_cpu_map[i].start < 0x400000) { if (cart_boot) { main_cpu_map[i].start |= 0x400000; main_cpu_map[i].end |= 0x400000; @@ -1659,13 +1750,11 @@ } } } - //TODO: support BRAM cart main_cpu_map[0].buffer = cd->rom_mut; main_cpu_map[2].buffer = cd->rom; main_cpu_map[1].buffer = cd->prog_ram; main_cpu_map[3].buffer = cd->word_ram; main_cpu_map[4].buffer = cd->word_ram + 0x10000; - *num_chunks = sizeof(main_cpu_map) / sizeof(*main_cpu_map); return main_cpu_map; } diff -r 9ead0fe69d9b -r b9fed07f19e4 segacd.h --- a/segacd.h Sun Jan 08 14:42:24 2023 -0800 +++ b/segacd.h Sun Jan 08 23:30:28 2023 -0800 @@ -16,6 +16,7 @@ uint16_t *prog_ram; uint16_t *word_ram; uint8_t *bram; + uint8_t *bram_cart; uint32_t stopwatch_cycle; uint32_t int2_cycle; uint32_t graphics_int_cycle; @@ -47,6 +48,8 @@ uint8_t main_swap_request; uint8_t bank_toggle; uint8_t sub_paused_wordram; + uint8_t bram_cart_write_enabled; + uint8_t bram_cart_id; rf5c164 pcm; lc8951 cdc; cdd_mcu cdd;