# HG changeset patch # User Michael Pavone # Date 1641092086 28800 # Node ID 3748a2a8a4b7812b61d3de5050ab806678becb0f # Parent 97bfb608927411056bf6d40a22807eb5fb728868 Support Sega mapper without 'SEGA SSF' in header or ROM DB entry and implement a subset of the extended Sega mapper implemented in the Mega Everdrive when 'SEGA SSF' is present diff -r 97bfb6089274 -r 3748a2a8a4b7 genesis.c --- a/genesis.c Fri Dec 31 13:03:21 2021 -0800 +++ b/genesis.c Sat Jan 01 18:54:46 2022 -0800 @@ -38,7 +38,7 @@ #ifdef IS_LIB #define MAX_SOUND_CYCLES (MCLKS_PER_YM*NUM_OPERATORS*6*4) #else -#define MAX_SOUND_CYCLES 100000 +#define MAX_SOUND_CYCLES 100000 #endif #ifdef NEW_CORE @@ -56,53 +56,53 @@ start_section(buf, SECTION_68000); m68k_serialize(gen->m68k, m68k_pc, buf); end_section(buf); - + start_section(buf, SECTION_Z80); z80_serialize(gen->z80, buf); end_section(buf); } - + start_section(buf, SECTION_VDP); vdp_serialize(gen->vdp, buf); end_section(buf); - + start_section(buf, SECTION_YM2612); ym_serialize(gen->ym, buf); end_section(buf); - + start_section(buf, SECTION_PSG); psg_serialize(gen->psg, buf); end_section(buf); - + if (all) { start_section(buf, SECTION_GEN_BUS_ARBITER); save_int8(buf, gen->z80->reset); save_int8(buf, gen->z80->busreq); save_int16(buf, gen->z80_bank_reg); end_section(buf); - + start_section(buf, SECTION_SEGA_IO_1); io_serialize(gen->io.ports, buf); end_section(buf); - + start_section(buf, SECTION_SEGA_IO_2); io_serialize(gen->io.ports + 1, buf); end_section(buf); - + start_section(buf, SECTION_SEGA_IO_EXT); io_serialize(gen->io.ports + 2, buf); end_section(buf); - + start_section(buf, SECTION_MAIN_RAM); save_int8(buf, RAM_WORDS * 2 / 1024); save_buffer16(buf, gen->work_ram, RAM_WORDS); end_section(buf); - + start_section(buf, SECTION_SOUND_RAM); save_int8(buf, Z80_RAM_BYTES / 1024); save_buffer8(buf, gen->zram, Z80_RAM_BYTES); end_section(buf); - + if (gen->version_reg & 0xF) { //only save TMSS info if it's present //that will allow a state saved on a model lacking TMSS @@ -112,7 +112,7 @@ save_buffer16(buf, gen->tmss_lock, 2); end_section(buf); } - + cart_serialize(&gen->header, buf); } } @@ -250,7 +250,7 @@ if ((address >= 0xA00000 && address < 0xB00000) || (address >= 0xC00000 && address <= 0xE00000)) { return 0; } - + //addresses here are word addresses (i.e. bit 0 corresponds to A1), so no need to do multiply by 2 return read_word(address * 2, (void **)genesis->m68k->mem_pointers, &genesis->m68k->options->gen, genesis->m68k); } @@ -290,7 +290,7 @@ uint32_t next_eint_port0 = io_next_interrupt(gen->io.ports, context->current_cycle); uint32_t next_eint_port1 = io_next_interrupt(gen->io.ports + 1, context->current_cycle); uint32_t next_eint_port2 = io_next_interrupt(gen->io.ports + 2, context->current_cycle); - uint32_t next_eint = next_eint_port0 < next_eint_port1 + uint32_t next_eint = next_eint_port0 < next_eint_port1 ? (next_eint_port0 < next_eint_port2 ? next_eint_port0 : next_eint_port2) : (next_eint_port1 < next_eint_port2 ? next_eint_port1 : next_eint_port2); if (next_eint != CYCLE_NEVER) { @@ -310,7 +310,7 @@ printf("int cycle changed to: %d, level: %d @ %d(%d), frame: %d, vcounter: %d, hslot: %d, mask: %d, hint_counter: %d\n", context->int_cycle, context->int_num, v_context->cycles, context->current_cycle, v_context->frame, v_context->vcounter, v_context->hslot, context->status & 0x7, v_context->hint_counter); old_int_cycle = context->int_cycle; }*/ - + if (context->status & M68K_STATUS_TRACE || context->trace_pending) { context->target_cycle = context->current_cycle; return; @@ -335,7 +335,7 @@ } else { context->target_cycle = context->sync_cycle = context->current_cycle; } - + } /*printf("Cyc: %d, Trgt: %d, Int Cyc: %d, Int: %d, Mask: %X, V: %d, H: %d, HICount: %d, HReg: %d, Line: %d\n", context->current_cycle, context->target_cycle, context->int_cycle, context->int_num, (context->status & 0x7), @@ -610,7 +610,7 @@ gen->bus_busy = 0; } } - + if (blocked < 0) { blocked = vdp_control_port_write(v_context, value); } else { @@ -1308,7 +1308,7 @@ } else { gen->version_reg = NO_DISK | USA; } - + if (region & HZ50) { gen->normal_clock = MCLKS_PAL; gen->soft_flush_cycles = MCLKS_LINE * 262 / 3 + 2; @@ -1514,6 +1514,9 @@ free(gen->header.save_dir); free_rom_info(&gen->header.info); free(gen->lock_on); + if (gen->save_type != SAVE_NONE && gen->mapper_type != MAPPER_SEGA_MED_V2) { + free(gen->save_storage); + } free(gen); } @@ -1578,7 +1581,7 @@ render_audio_source_gaindb(gen->psg->audio, config_gain ? atof(config_gain) : 0.0f); config_gain = tern_find_path(config, "audio\0fm_gain\0", TVAL_PTR).ptrval; render_audio_source_gaindb(gen->ym->audio, config_gain ? atof(config_gain) : 0.0f); - + char *config_dac = tern_find_path_default(config, "audio\0fm_dac\0", (tern_val){.ptrval="zero_offset"}, TVAL_PTR).ptrval; ym_enable_zero_offset(gen->ym, !strcmp(config_dac, "zero_offset")); } @@ -1621,7 +1624,7 @@ if (gen->tmss) { return gen->tmss_write_16(address, context, value); } - + return context; } @@ -1632,7 +1635,7 @@ if (gen->tmss) { return gen->tmss_write_8(address, context, value); } - + return context; } @@ -1670,7 +1673,7 @@ *dest = value; m68k_handle_code_write(address, m68k); } - + return context; } @@ -1688,7 +1691,7 @@ #endif m68k_handle_code_write(address & ~1, m68k); } - + return context; } @@ -1797,10 +1800,10 @@ gen->max_cycles = config_cycles ? atoi(config_cycles) : DEFAULT_SYNC_INTERVAL; gen->int_latency_prev1 = MCLKS_PER_68K * 32; gen->int_latency_prev2 = MCLKS_PER_68K * 16; - + render_set_video_standard((gen->version_reg & HZ50) ? VID_PAL : VID_NTSC); event_system_start(SYSTEM_GENESIS, (gen->version_reg & HZ50) ? VID_PAL : VID_NTSC, rom->name); - + gen->ym = malloc(sizeof(ym2612_context)); char *fm = tern_find_ptr_default(model, "fm", "discrete 2612"); if (!strcmp(fm + strlen(fm) -4, "3834")) { @@ -1810,7 +1813,7 @@ gen->psg = malloc(sizeof(psg_context)); psg_init(gen->psg, gen->master_clock, MCLKS_PER_PSG); - + set_audio_config(gen); z80_map[0].buffer = gen->zram = calloc(1, Z80_RAM_BYTES); @@ -1881,9 +1884,9 @@ } else { gen->save_storage = NULL; } - + gen->mapper_start_index = rom->mapper_start_index; - + //This must happen before we generate memory access functions in init_m68k_opts uint8_t next_ptr_index = 0; uint32_t tmss_min_alloc = 16 * 1024; @@ -2031,7 +2034,7 @@ gen->m68k = init_68k_context(opts, NULL); gen->m68k->system = gen; opts->address_log = (system_opts & OPT_ADDRESS_LOG) ? fopen("address.log", "w") : NULL; - + //This must happen after the 68K context has been allocated for (int i = 0; i < rom->map_chunks; i++) { @@ -2039,7 +2042,7 @@ gen->m68k->mem_pointers[rom->map[i].ptr_index] = rom->map[i].buffer; } } - + if (gen->mapper_type == MAPPER_SEGA) { //initialize bank registers for (int i = 1; i < sizeof(gen->bank_regs); i++) diff -r 97bfb6089274 -r 3748a2a8a4b7 genesis.h --- a/genesis.h Fri Dec 31 13:03:21 2021 -0800 +++ b/genesis.h Sat Jan 01 18:54:46 2022 -0800 @@ -61,11 +61,11 @@ uint32_t last_flush_cycle; uint32_t soft_flush_cycles; uint32_t tmss_write_offset; - uint8_t bank_regs[8]; uint16_t z80_bank_reg; uint16_t tmss_lock[2]; uint16_t mapper_start_index; uint8_t mapper_type; + uint8_t bank_regs[9]; uint8_t save_type; sega_io io; uint8_t version_reg; diff -r 97bfb6089274 -r 3748a2a8a4b7 rom.db --- a/rom.db Fri Dec 31 13:03:21 2021 -0800 +++ b/rom.db Sat Jan 01 18:54:46 2022 -0800 @@ -779,7 +779,7 @@ last 3FFFFF } } - + } MK-1563 { name Sonic & Knuckles @@ -1287,7 +1287,7 @@ } 7313c20071de0ab1cd84ac1352cb0ed1c4a4afa8 { - #This appears to be an underdump, but it seems to be the only copy floating around + #This appears to be an underdump, but it seems to be the only copy floating around name 12-in-1 map { 0 { @@ -1377,20 +1377,6 @@ } } } -NETO-001 { - name Sonic Delta - map { - 0 { - device ROM - last 7FFFF - } - 80000 { - device Sega mapper - last 3FFFFF - offset 80000 - } - } -} 5e5ca20b39122c86b8f662bd8014af674f9dbed7 { name Rock Heaven map { @@ -1422,7 +1408,7 @@ value A000 last 500209 } - + } } T-122026 { diff -r 97bfb6089274 -r 3748a2a8a4b7 romdb.c --- a/romdb.c Fri Dec 31 13:03:21 2021 -0800 +++ b/romdb.c Sat Jan 01 18:54:46 2022 -0800 @@ -80,6 +80,7 @@ { case MAPPER_SEGA: case MAPPER_SEGA_SRAM: + case MAPPER_SEGA_MED_V2: sega_mapper_serialize(gen, buf); break; case MAPPER_REALTEC: @@ -126,7 +127,7 @@ //TODO: Should probably prefer the title field that corresponds to the user's region preference uint8_t *last = rom + TITLE_END - 1; uint8_t *src = rom + TITLE_START; - + for (;;) { while (last > src && (*last <= 0x20 || *last >= 0x80)) @@ -169,7 +170,7 @@ uint8_t region_bits[] = {REGION_J, REGION_U, REGION_E, REGION_J|REGION_U|REGION_E}; uint8_t translate_region_char(uint8_t c) -{ +{ for (int i = 0; i < sizeof(region_bits); i++) { if (c == region_chars[i]) { @@ -226,7 +227,7 @@ uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size) { - return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; + return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; } uint32_t read_ram_header(rom_info *info, uint8_t *rom) @@ -253,44 +254,86 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) { uint32_t rom_end = get_u32be(rom + ROM_END) + 1; + uint32_t rom_end_raw = rom_end; if (size > rom_end) { rom_end = size; } else if (rom_end > nearest_pow2(size)) { rom_end = nearest_pow2(size); } info->save_type = SAVE_NONE; - if (size >= 0x80000 && !memcmp("SEGA SSF", rom + 0x100, 8)) { + uint8_t is_med_ssf = size >= 0x108 && !memcmp("SEGA SSF", rom + 0x100, 8); + if (is_med_ssf || (size >= 0x400000 && rom_end_raw <= 0x400000)) { + if (is_med_ssf && rom_end < 16*1024*1024) { + info->rom = rom = realloc(rom, 16*1024*1024); + } info->mapper_start_index = 0; - info->mapper_type = MAPPER_SEGA; + info->mapper_type = is_med_ssf ? MAPPER_SEGA_MED_V2 : MAPPER_SEGA; info->map_chunks = base_chunks + 9; info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); memset(info->map, 0, sizeof(memmap_chunk)*9); memcpy(info->map+9, base_map, sizeof(memmap_chunk) * base_chunks); - - info->map[0].start = 0; - info->map[0].end = 0x80000; - info->map[0].mask = 0xFFFFFF; - info->map[0].flags = MMAP_READ; - info->map[0].buffer = rom; - - if (has_ram_header(rom, size)){ - read_ram_header(info, rom); + + int i; + uint16_t map_flags; + if (is_med_ssf) { + i = 0; + map_flags = info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE; + info->save_type = RAM_FLAG_BOTH; + info->save_size = 256*1024; + info->save_mask = info->save_size - 1; + info->save_buffer = rom + 16*1024*1024 - 256*1024; + } else { + i = 1; + map_flags = info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; + info->map[0].start = 0; + info->map[0].end = 0x80000; + info->map[0].mask = 0xFFFFFF; + info->map[0].flags = MMAP_READ; + info->map[0].buffer = rom; + + if (has_ram_header(rom, size)){ + read_ram_header(info, rom); + } } - - for (int i = 1; i < 8; i++) + static const write_8_fun med_w8[] = { + write_med_ram0_b, + write_med_ram1_b, + write_med_ram2_b, + write_med_ram3_b, + write_med_ram4_b, + write_med_ram5_b, + write_med_ram6_b, + write_med_ram7_b, + }; + static const write_16_fun med_w16[] = { + write_med_ram0_w, + write_med_ram1_w, + write_med_ram2_w, + write_med_ram3_w, + write_med_ram4_w, + write_med_ram5_w, + write_med_ram6_w, + write_med_ram7_w, + }; + + for (; i < 8; i++) { info->map[i].start = i * 0x80000; info->map[i].end = (i + 1) * 0x80000; info->map[i].mask = 0x7FFFF; info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom; info->map[i].ptr_index = i; - info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; - - info->map[i].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL - info->map[i].read_8 = (read_8_fun)read_sram_b; - info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area - info->map[i].write_8 = (write_8_fun)write_sram_area_b; - + info->map[i].flags = map_flags; + + info->map[i].read_16 = is_med_ssf ? NULL : (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL + info->map[i].read_8 = is_med_ssf ? NULL : (read_8_fun)read_sram_b; + if (is_med_ssf) { + info->map[i].write_16 = med_w16[i]; + info->map[i].write_8 = med_w8[i]; + } else { + info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area + info->map[i].write_8 = (write_8_fun)write_sram_area_b; + } } info->map[8].start = 0xA13000; info->map[8].end = 0xA13100; @@ -327,7 +370,7 @@ info->map[1].end = 0xA130D0; info->map[1].mask = 0xFFFFFF; if (!strcmp( - "on", + "on", tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) ) { info->map[1].write_16 = megawifi_write_w; @@ -388,7 +431,7 @@ info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area info->map[1].write_8 = (write_8_fun)write_sram_area_b; info->map[1].buffer = rom + 0x200000; - + //Last entry in the base map is a catch all one that needs to be //after all the other entries memmap_chunk *unused = info->map + info->map_chunks - 2; @@ -405,7 +448,7 @@ return; } } - + info->map_chunks = base_chunks + 1; info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); memset(info->map, 0, sizeof(memmap_chunk)); @@ -743,7 +786,7 @@ } } else if (!strcmp(dtype, "NOR")) { process_nor_def(key, state); - + map->write_16 = nor_flash_write_w; map->write_8 = nor_flash_write_b; map->read_16 = nor_flash_read_w; @@ -868,7 +911,7 @@ map->write_8 = write_multi_game_b; } else if (!strcmp(dtype, "megawifi")) { if (!strcmp( - "on", + "on", tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) ) { map->write_16 = megawifi_write_w; @@ -965,14 +1008,14 @@ info.num_eeprom = 0; memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); map_iter_state state = { - .info = &info, - .rom = rom, + .info = &info, + .rom = rom, .lock_on = lock_on, .root = entry, .rom_db = rom_db, - .rom_size = rom_size, + .rom_size = rom_size, .lock_on_size = lock_on_size, - .index = 0, + .index = 0, .num_els = info.map_chunks - base_chunks, .ptr_index = 0 }; diff -r 97bfb6089274 -r 3748a2a8a4b7 romdb.h --- a/romdb.h Fri Dec 31 13:03:21 2021 -0800 +++ b/romdb.h Sat Jan 01 18:54:46 2022 -0800 @@ -48,7 +48,8 @@ MAPPER_REALTEC, MAPPER_XBAND, MAPPER_MULTI_GAME, - MAPPER_JCART + MAPPER_JCART, + MAPPER_SEGA_MED_V2 }; diff -r 97bfb6089274 -r 3748a2a8a4b7 sega_mapper.c --- a/sega_mapper.c Fri Dec 31 13:03:21 2021 -0800 +++ b/sega_mapper.c Sat Jan 01 18:54:46 2022 -0800 @@ -1,4 +1,5 @@ #include "genesis.h" +#include "util.h" uint16_t read_sram_w(uint32_t address, m68k_context * context) { @@ -43,6 +44,14 @@ m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value) { genesis_context * gen = context->system; + if (gen->mapper_type == MAPPER_SEGA_MED_V2) { + if (gen->bank_regs[8] & 0x20) { + uint32_t bank = address >> 19; + address &= 0x7FFFF; + context->mem_pointers[gen->mapper_start_index + bank][address >> 1] = value; + } + return context; + } if ((gen->bank_regs[0] & 0x3) == 1) { address &= gen->save_ram_mask; switch(gen->save_type) @@ -87,14 +96,128 @@ return context; } +static void* write_med_ram_w(uint32_t address, void *vcontext, uint16_t value, uint16_t bank) +{ + m68k_context *context = vcontext; + genesis_context * gen = context->system; + if (gen->bank_regs[8] & 0x20) { + context->mem_pointers[gen->mapper_start_index + bank][address >> 1] = value; + address += bank * 0x80000; + m68k_invalidate_code_range(gen->m68k, address, address + 2); + } + return vcontext; +} + +void* write_med_ram0_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 0); +} + +void* write_med_ram1_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 1); +} + +void* write_med_ram2_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 2); +} + +void* write_med_ram3_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 3); +} + +void* write_med_ram4_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 4); +} + +void* write_med_ram5_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 5); +} + +void* write_med_ram6_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 6); +} + +void* write_med_ram7_w(uint32_t address, void *vcontext, uint16_t value) +{ + return write_med_ram_w(address, vcontext, value, 7); +} + +static void* write_med_ram_b(uint32_t address, void *vcontext, uint8_t value, uint16_t bank) +{ + m68k_context *context = vcontext; + genesis_context * gen = context->system; + if (gen->bank_regs[8] & 0x20) { + ((uint8_t*)context->mem_pointers[gen->mapper_start_index + bank])[address ^ 1] = value; + address += bank * 0x80000; + m68k_invalidate_code_range(gen->m68k, address, address + 1); + } + return vcontext; +} + +void* write_med_ram0_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 0); +} + +void* write_med_ram1_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 1); +} + +void* write_med_ram2_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 2); +} + +void* write_med_ram3_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 3); +} + +void* write_med_ram4_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 4); +} + +void* write_med_ram5_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 5); +} + +void* write_med_ram6_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 6); +} + +void* write_med_ram7_b(uint32_t address, void *vcontext, uint8_t value) +{ + return write_med_ram_b(address, vcontext, value, 7); +} + m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value) { genesis_context * gen = context->system; address &= 0xE; address >>= 1; - gen->bank_regs[address] = value; if (!address) { - if (value & 1) { + if (gen->mapper_type == MAPPER_SEGA_MED_V2) { + if (!value & 0x8000) { + //writes without protection bit set are ignored + return context; + } + gen->bank_regs[8] = value >> 8; + void *new_ptr = gen->cart + 0x40000*(value & 0x1F); + if (context->mem_pointers[gen->mapper_start_index] != new_ptr) { + m68k_invalidate_code_range(gen->m68k, 0, 0x80000); + context->mem_pointers[gen->mapper_start_index] = new_ptr; + } + } else if (value & 1) { //Used for games that only use the mapper for SRAM if (context->mem_pointers[gen->mapper_start_index]) { gen->mapper_temp = context->mem_pointers[gen->mapper_start_index]; @@ -116,19 +239,30 @@ context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i]; } } - } else if (gen->mapper_type == MAPPER_SEGA) { - void *new_ptr = gen->cart + 0x40000*value; + } else if (gen->mapper_type != MAPPER_SEGA_SRAM) { + uint32_t mask = ((gen->mapper_type == MAPPER_SEGA_MED_V2 ? (16 *1024 * 1024) : nearest_pow2(gen->header.info.rom_size)) >> 1) - 1; + void *new_ptr = gen->cart + ((0x40000*value) & mask); if (context->mem_pointers[gen->mapper_start_index + address] != new_ptr) { m68k_invalidate_code_range(gen->m68k, address * 0x80000, (address + 1) * 0x80000); context->mem_pointers[gen->mapper_start_index + address] = new_ptr; } } + gen->bank_regs[address] = value; return context; } m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value) { - if (address & 1) { + genesis_context * gen = context->system; + if (gen->mapper_type == MAPPER_SEGA_MED_V2) { + address &= 0xF; + if (!address) { + //not sure if this is correct, possible byte sized writes are always rejected to $A130F0 + write_bank_reg_w(address, context, value << 8 | value); + } else if (address > 2 && (address & 1)) { + write_bank_reg_w(address, context, value); + } + } else if (address & 1) { write_bank_reg_w(address, context, value); } return context; @@ -136,13 +270,23 @@ void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf) { - save_buffer8(buf, gen->bank_regs, sizeof(gen->bank_regs)); + save_buffer8(buf, gen->bank_regs, gen->mapper_type == MAPPER_SEGA_MED_V2 ? sizeof(gen->bank_regs) : sizeof(gen->bank_regs) - 1); } void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen) { - for (int i = 0; i < sizeof(gen->bank_regs); i++) - { - write_bank_reg_w(i * 2, gen->m68k, load_int8(buf)); + if (gen->mapper_type == MAPPER_SEGA_MED_V2) { + uint16_t reg0 = load_int8(buf); + for (int i = 1; i < sizeof(gen->bank_regs) - 1; i++) + { + write_bank_reg_w(i * 2, gen->m68k, load_int8(buf)); + } + reg0 |= load_int8(buf) << 8; + write_bank_reg_w(0, gen->m68k, reg0); + } else { + for (int i = 0; i < sizeof(gen->bank_regs) - 1; i++) + { + write_bank_reg_w(i * 2, gen->m68k, load_int8(buf)); + } } } diff -r 97bfb6089274 -r 3748a2a8a4b7 sega_mapper.h --- a/sega_mapper.h Fri Dec 31 13:03:21 2021 -0800 +++ b/sega_mapper.h Sat Jan 01 18:54:46 2022 -0800 @@ -8,6 +8,22 @@ m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8_t value); m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value); m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value); +void* write_med_ram0_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram1_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram2_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram3_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram4_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram5_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram6_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram7_w(uint32_t address, void *vcontext, uint16_t value); +void* write_med_ram0_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram1_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram2_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram3_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram4_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram5_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram6_b(uint32_t address, void *vcontext, uint8_t value); +void* write_med_ram7_b(uint32_t address, void *vcontext, uint8_t value); void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf); void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen);