# HG changeset patch # User Michael Pavone # Date 1498150181 25200 # Node ID 780fbe0b97becf2a90f07d53e62a61f76b7fd4f0 # Parent 4cd4aa6be5f61e7671339cc43f886b5cf361d749 WIP support for handling S3 save RAM when locked on diff -r 4cd4aa6be5f6 -r 780fbe0b97be romdb.c --- a/romdb.c Tue Jun 20 22:56:07 2017 -0700 +++ b/romdb.c Thu Jun 22 09:49:41 2017 -0700 @@ -616,6 +616,22 @@ return db; } +void free_rom_info(rom_info *info) +{ + free(info->name); + if (info->save_type != SAVE_NONE) { + free(info->save_buffer); + if (info->save_type == SAVE_I2C) { + free(info->eeprom_map); + } + } + free(info->map); + free(info->port1_override); + free(info->port2_override); + free(info->ext_override); + free(info->mouse_mode); +} + char *get_header_name(uint8_t *rom) { //TODO: Should probably prefer the title field that corresponds to the user's region preference @@ -870,6 +886,7 @@ uint8_t *rom; uint8_t *lock_on; tern_node *root; + tern_node *rom_db; uint32_t rom_size; uint32_t lock_on_size; int index; @@ -1051,58 +1068,64 @@ map->flags = MMAP_READ; map->mask = calc_mask(state->rom_size - offset, start, end); } else if (!strcmp(dtype, "LOCK-ON")) { - map->flags = MMAP_READ; + rom_info lock_info; if (state->lock_on) { - if (state->lock_on_size > offset) { - map->mask = calc_mask(state->lock_on_size - offset, start, end); - } else { - map->mask = calc_mask(state->lock_on_size, start, end); - } - map->buffer = state->lock_on + (offset & (nearest_pow2(state->lock_on_size) - 1)); + lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0); } else if (state->rom_size > start) { //This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks - map->buffer = state->rom + start; - map->mask = calc_mask(state->rom_size - start, start, end); - if (has_ram_header(map->buffer, state->rom_size - start)) { - uint32_t sram_start = read_ram_header(state->info, map->buffer); - - state->info->map_chunks+=1; - state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); - memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1); - if (sram_start >= state->rom_size) { - map = state->info->map + ++state->index; - map->start = sram_start; - map->mask = state->info->save_mask; - map->end = sram_start + state->info->save_mask + 1; - map->flags = MMAP_READ | MMAP_WRITE; - if (state->info->save_type == RAM_FLAG_ODD) { - map->flags |= MMAP_ONLY_ODD; - } else if (state->info->save_type == RAM_FLAG_EVEN) { - map->flags |= MMAP_ONLY_EVEN; - } - map->buffer = state->info->save_buffer; - } else { - map = state->info->map + state->index++; - map->flags |= MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL; - state->info->mapper_start_index = state->ptr_index++; - map->ptr_index = state->info->mapper_start_index; - map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[ptr_idx] == NULL - map->read_8 = (read_8_fun)read_sram_b; - map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area - map->write_8 = (write_8_fun)write_sram_area_b; - - map = state->info->map + state->index; - map->start = 0xA13000; - map->end = 0xA13100; - map->mask = 0xFF; - map->write_16 = (write_16_fun)write_bank_reg_w; - map->write_8 = (write_8_fun)write_bank_reg_b; - } - } + lock_info = configure_rom(state->rom_db, state->rom + start, state->rom_size - start, NULL, 0, NULL, 0); } else { //skip this entry if there is no lock on cartridge attached return; } + uint32_t matching_chunks = 0; + for (int i = 0; i < lock_info.map_chunks; i++) + { + if (lock_info.map[i].start < 0xC00000 && lock_info.map[i].end > 0x200000) { + matching_chunks++; + } + } + if (matching_chunks == 0) { + //Nothing mapped in the relevant range for the lock-on cart, ignore this mapping + return; + } else if (matching_chunks > 1) { + state->info->map_chunks += matching_chunks - 1; + state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); + memset(state->info->map + state->info->map_chunks - (matching_chunks - 1), 0, sizeof(memmap_chunk) * (matching_chunks - 1)); + map = state->info->map + state->index; + } + for (int i = 0; i < matching_chunks; i++) + { + if (lock_info.map[i].start >= 0xC00000 || lock_info.map[i].end <= 0x200000) { + continue; + } + *map = lock_info.map[i]; + if (map->start < 0x200000) { + if (map->buffer) { + map->buffer += (0x200000 - map->start) & ((map->flags & MMAP_AUX_BUFF) ? map->aux_mask : map->mask); + } + map->start = 0x200000; + } + map++; + state->index++; + } + if (state->info->save_type == SAVE_NONE && lock_info.save_type != SAVE_NONE) { + //main cart has no save device, but lock-on cart does + if (state->lock_on) { + state->info->is_save_lock_on = 1; + } + state->info->save_buffer = lock_info.save_buffer; + state->info->save_size = lock_info.save_size; + state->info->save_mask = lock_info.save_mask; + state->info->save_page_size = lock_info.save_page_size; + state->info->save_product_id = lock_info.save_product_id; + state->info->save_type = lock_info.save_type; + state->info->save_bus = lock_info.save_bus; + lock_info.save_buffer = NULL; + lock_info.save_type = SAVE_NONE; + } + free_rom_info(&lock_info); + return; } else if (!strcmp(dtype, "EEPROM")) { process_eeprom_def(key, state); add_eeprom_map(node, start, end, state); @@ -1282,7 +1305,8 @@ .info = &info, .rom = rom, .lock_on = lock_on, - .root = entry, + .root = entry, + .rom_db = rom_db, .rom_size = rom_size, .lock_on_size = lock_on_size, .index = 0, diff -r 4cd4aa6be5f6 -r 780fbe0b97be romdb.h --- a/romdb.h Tue Jun 20 22:56:07 2017 -0700 +++ b/romdb.h Thu Jun 22 09:49:41 2017 -0700 @@ -73,6 +73,7 @@ uint8_t save_type; uint8_t save_bus; //only used for NOR currently uint8_t regions; + uint8_t is_save_lock_on; //Does the save buffer actually belong to a lock-on cart? }; #define GAME_ID_OFF 0x183 @@ -85,5 +86,8 @@ void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size); void nor_flash_init(nor_state *state, uint8_t *buffer, uint32_t size, uint32_t page_size, uint16_t product_id, uint8_t bus_flags); char const *save_type_name(uint8_t save_type); +//Note: free_rom_info only frees things pointed to by a rom_info struct, not the struct itself +//this is because rom_info structs are typically stack allocated +void free_rom_info(rom_info *info); #endif //ROMDB_H_ diff -r 4cd4aa6be5f6 -r 780fbe0b97be xband.c --- a/xband.c Tue Jun 20 22:56:07 2017 -0700 +++ b/xband.c Thu Jun 22 09:49:41 2017 -0700 @@ -300,19 +300,7 @@ rom_info lock_on_info = configure_rom(rom_db, lock_on, lock_on_size, NULL, 0, base_map, base_chunks); info.name = alloc_concat("XBAND - ", lock_on_info.name); info.regions = lock_on_info.regions; - //TODO: Move this to a shared function in romdbc.h - free(lock_on_info.name); - if (lock_on_info.save_type != SAVE_NONE) { - free(lock_on_info.save_buffer); - if (lock_on_info.save_type == SAVE_I2C) { - free(lock_on_info.eeprom_map); - } - } - free(lock_on_info.map); - free(lock_on_info.port1_override); - free(lock_on_info.port2_override); - free(lock_on_info.ext_override); - free(lock_on_info.mouse_mode); + free_rom_info(&lock_on_info); } else { info.name = strdup("XBAND"); info.regions = REGION_J|REGION_U|REGION_E;