comparison romdb.c @ 1411:780fbe0b97be

WIP support for handling S3 save RAM when locked on
author Michael Pavone <pavone@retrodev.com>
date Thu, 22 Jun 2017 09:49:41 -0700
parents 4cd4aa6be5f6
children 3d7f668dce3d
comparison
equal deleted inserted replaced
1410:4cd4aa6be5f6 1411:780fbe0b97be
614 fatal_error("Failed to load ROM DB\n"); 614 fatal_error("Failed to load ROM DB\n");
615 } 615 }
616 return db; 616 return db;
617 } 617 }
618 618
619 void free_rom_info(rom_info *info)
620 {
621 free(info->name);
622 if (info->save_type != SAVE_NONE) {
623 free(info->save_buffer);
624 if (info->save_type == SAVE_I2C) {
625 free(info->eeprom_map);
626 }
627 }
628 free(info->map);
629 free(info->port1_override);
630 free(info->port2_override);
631 free(info->ext_override);
632 free(info->mouse_mode);
633 }
634
619 char *get_header_name(uint8_t *rom) 635 char *get_header_name(uint8_t *rom)
620 { 636 {
621 //TODO: Should probably prefer the title field that corresponds to the user's region preference 637 //TODO: Should probably prefer the title field that corresponds to the user's region preference
622 uint8_t *last = rom + TITLE_END - 1; 638 uint8_t *last = rom + TITLE_END - 1;
623 uint8_t *src = rom + TITLE_START; 639 uint8_t *src = rom + TITLE_START;
868 typedef struct { 884 typedef struct {
869 rom_info *info; 885 rom_info *info;
870 uint8_t *rom; 886 uint8_t *rom;
871 uint8_t *lock_on; 887 uint8_t *lock_on;
872 tern_node *root; 888 tern_node *root;
889 tern_node *rom_db;
873 uint32_t rom_size; 890 uint32_t rom_size;
874 uint32_t lock_on_size; 891 uint32_t lock_on_size;
875 int index; 892 int index;
876 int num_els; 893 int num_els;
877 uint16_t ptr_index; 894 uint16_t ptr_index;
1049 if (!strcmp(dtype, "ROM")) { 1066 if (!strcmp(dtype, "ROM")) {
1050 map->buffer = state->rom + offset; 1067 map->buffer = state->rom + offset;
1051 map->flags = MMAP_READ; 1068 map->flags = MMAP_READ;
1052 map->mask = calc_mask(state->rom_size - offset, start, end); 1069 map->mask = calc_mask(state->rom_size - offset, start, end);
1053 } else if (!strcmp(dtype, "LOCK-ON")) { 1070 } else if (!strcmp(dtype, "LOCK-ON")) {
1054 map->flags = MMAP_READ; 1071 rom_info lock_info;
1055 if (state->lock_on) { 1072 if (state->lock_on) {
1056 if (state->lock_on_size > offset) { 1073 lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0);
1057 map->mask = calc_mask(state->lock_on_size - offset, start, end);
1058 } else {
1059 map->mask = calc_mask(state->lock_on_size, start, end);
1060 }
1061 map->buffer = state->lock_on + (offset & (nearest_pow2(state->lock_on_size) - 1));
1062 } else if (state->rom_size > start) { 1074 } else if (state->rom_size > start) {
1063 //This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks 1075 //This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks
1064 map->buffer = state->rom + start; 1076 lock_info = configure_rom(state->rom_db, state->rom + start, state->rom_size - start, NULL, 0, NULL, 0);
1065 map->mask = calc_mask(state->rom_size - start, start, end);
1066 if (has_ram_header(map->buffer, state->rom_size - start)) {
1067 uint32_t sram_start = read_ram_header(state->info, map->buffer);
1068
1069 state->info->map_chunks+=1;
1070 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
1071 memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
1072 if (sram_start >= state->rom_size) {
1073 map = state->info->map + ++state->index;
1074 map->start = sram_start;
1075 map->mask = state->info->save_mask;
1076 map->end = sram_start + state->info->save_mask + 1;
1077 map->flags = MMAP_READ | MMAP_WRITE;
1078 if (state->info->save_type == RAM_FLAG_ODD) {
1079 map->flags |= MMAP_ONLY_ODD;
1080 } else if (state->info->save_type == RAM_FLAG_EVEN) {
1081 map->flags |= MMAP_ONLY_EVEN;
1082 }
1083 map->buffer = state->info->save_buffer;
1084 } else {
1085 map = state->info->map + state->index++;
1086 map->flags |= MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL;
1087 state->info->mapper_start_index = state->ptr_index++;
1088 map->ptr_index = state->info->mapper_start_index;
1089 map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[ptr_idx] == NULL
1090 map->read_8 = (read_8_fun)read_sram_b;
1091 map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
1092 map->write_8 = (write_8_fun)write_sram_area_b;
1093
1094 map = state->info->map + state->index;
1095 map->start = 0xA13000;
1096 map->end = 0xA13100;
1097 map->mask = 0xFF;
1098 map->write_16 = (write_16_fun)write_bank_reg_w;
1099 map->write_8 = (write_8_fun)write_bank_reg_b;
1100 }
1101 }
1102 } else { 1077 } else {
1103 //skip this entry if there is no lock on cartridge attached 1078 //skip this entry if there is no lock on cartridge attached
1104 return; 1079 return;
1105 } 1080 }
1081 uint32_t matching_chunks = 0;
1082 for (int i = 0; i < lock_info.map_chunks; i++)
1083 {
1084 if (lock_info.map[i].start < 0xC00000 && lock_info.map[i].end > 0x200000) {
1085 matching_chunks++;
1086 }
1087 }
1088 if (matching_chunks == 0) {
1089 //Nothing mapped in the relevant range for the lock-on cart, ignore this mapping
1090 return;
1091 } else if (matching_chunks > 1) {
1092 state->info->map_chunks += matching_chunks - 1;
1093 state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
1094 memset(state->info->map + state->info->map_chunks - (matching_chunks - 1), 0, sizeof(memmap_chunk) * (matching_chunks - 1));
1095 map = state->info->map + state->index;
1096 }
1097 for (int i = 0; i < matching_chunks; i++)
1098 {
1099 if (lock_info.map[i].start >= 0xC00000 || lock_info.map[i].end <= 0x200000) {
1100 continue;
1101 }
1102 *map = lock_info.map[i];
1103 if (map->start < 0x200000) {
1104 if (map->buffer) {
1105 map->buffer += (0x200000 - map->start) & ((map->flags & MMAP_AUX_BUFF) ? map->aux_mask : map->mask);
1106 }
1107 map->start = 0x200000;
1108 }
1109 map++;
1110 state->index++;
1111 }
1112 if (state->info->save_type == SAVE_NONE && lock_info.save_type != SAVE_NONE) {
1113 //main cart has no save device, but lock-on cart does
1114 if (state->lock_on) {
1115 state->info->is_save_lock_on = 1;
1116 }
1117 state->info->save_buffer = lock_info.save_buffer;
1118 state->info->save_size = lock_info.save_size;
1119 state->info->save_mask = lock_info.save_mask;
1120 state->info->save_page_size = lock_info.save_page_size;
1121 state->info->save_product_id = lock_info.save_product_id;
1122 state->info->save_type = lock_info.save_type;
1123 state->info->save_bus = lock_info.save_bus;
1124 lock_info.save_buffer = NULL;
1125 lock_info.save_type = SAVE_NONE;
1126 }
1127 free_rom_info(&lock_info);
1128 return;
1106 } else if (!strcmp(dtype, "EEPROM")) { 1129 } else if (!strcmp(dtype, "EEPROM")) {
1107 process_eeprom_def(key, state); 1130 process_eeprom_def(key, state);
1108 add_eeprom_map(node, start, end, state); 1131 add_eeprom_map(node, start, end, state);
1109 1132
1110 map->write_16 = write_eeprom_i2c_w; 1133 map->write_16 = write_eeprom_i2c_w;
1280 memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); 1303 memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks);
1281 map_iter_state state = { 1304 map_iter_state state = {
1282 .info = &info, 1305 .info = &info,
1283 .rom = rom, 1306 .rom = rom,
1284 .lock_on = lock_on, 1307 .lock_on = lock_on,
1285 .root = entry, 1308 .root = entry,
1309 .rom_db = rom_db,
1286 .rom_size = rom_size, 1310 .rom_size = rom_size,
1287 .lock_on_size = lock_on_size, 1311 .lock_on_size = lock_on_size,
1288 .index = 0, 1312 .index = 0,
1289 .num_els = info.map_chunks - base_chunks, 1313 .num_els = info.map_chunks - base_chunks,
1290 .ptr_index = 0 1314 .ptr_index = 0