comparison romdb.c @ 2052:3748a2a8a4b7

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
author Michael Pavone <pavone@retrodev.com>
date Sat, 01 Jan 2022 18:54:46 -0800
parents 8b2ef428d1aa
children 3414a4423de1
comparison
equal deleted inserted replaced
2051:97bfb6089274 2052:3748a2a8a4b7
78 save_int8(buf, gen->mapper_type); 78 save_int8(buf, gen->mapper_type);
79 switch(gen->mapper_type) 79 switch(gen->mapper_type)
80 { 80 {
81 case MAPPER_SEGA: 81 case MAPPER_SEGA:
82 case MAPPER_SEGA_SRAM: 82 case MAPPER_SEGA_SRAM:
83 case MAPPER_SEGA_MED_V2:
83 sega_mapper_serialize(gen, buf); 84 sega_mapper_serialize(gen, buf);
84 break; 85 break;
85 case MAPPER_REALTEC: 86 case MAPPER_REALTEC:
86 realtec_serialize(gen, buf); 87 realtec_serialize(gen, buf);
87 break; 88 break;
124 char *get_header_name(uint8_t *rom) 125 char *get_header_name(uint8_t *rom)
125 { 126 {
126 //TODO: Should probably prefer the title field that corresponds to the user's region preference 127 //TODO: Should probably prefer the title field that corresponds to the user's region preference
127 uint8_t *last = rom + TITLE_END - 1; 128 uint8_t *last = rom + TITLE_END - 1;
128 uint8_t *src = rom + TITLE_START; 129 uint8_t *src = rom + TITLE_START;
129 130
130 for (;;) 131 for (;;)
131 { 132 {
132 while (last > src && (*last <= 0x20 || *last >= 0x80)) 133 while (last > src && (*last <= 0x20 || *last >= 0x80))
133 { 134 {
134 last--; 135 last--;
167 168
168 char *region_chars = "JUEW"; 169 char *region_chars = "JUEW";
169 uint8_t region_bits[] = {REGION_J, REGION_U, REGION_E, REGION_J|REGION_U|REGION_E}; 170 uint8_t region_bits[] = {REGION_J, REGION_U, REGION_E, REGION_J|REGION_U|REGION_E};
170 171
171 uint8_t translate_region_char(uint8_t c) 172 uint8_t translate_region_char(uint8_t c)
172 { 173 {
173 for (int i = 0; i < sizeof(region_bits); i++) 174 for (int i = 0; i < sizeof(region_bits); i++)
174 { 175 {
175 if (c == region_chars[i]) { 176 if (c == region_chars[i]) {
176 return region_bits[i]; 177 return region_bits[i];
177 } 178 }
224 } 225 }
225 } 226 }
226 227
227 uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size) 228 uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size)
228 { 229 {
229 return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; 230 return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A';
230 } 231 }
231 232
232 uint32_t read_ram_header(rom_info *info, uint8_t *rom) 233 uint32_t read_ram_header(rom_info *info, uint8_t *rom)
233 { 234 {
234 uint32_t ram_start = get_u32be(rom + RAM_START); 235 uint32_t ram_start = get_u32be(rom + RAM_START);
251 } 252 }
252 253
253 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) 254 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks)
254 { 255 {
255 uint32_t rom_end = get_u32be(rom + ROM_END) + 1; 256 uint32_t rom_end = get_u32be(rom + ROM_END) + 1;
257 uint32_t rom_end_raw = rom_end;
256 if (size > rom_end) { 258 if (size > rom_end) {
257 rom_end = size; 259 rom_end = size;
258 } else if (rom_end > nearest_pow2(size)) { 260 } else if (rom_end > nearest_pow2(size)) {
259 rom_end = nearest_pow2(size); 261 rom_end = nearest_pow2(size);
260 } 262 }
261 info->save_type = SAVE_NONE; 263 info->save_type = SAVE_NONE;
262 if (size >= 0x80000 && !memcmp("SEGA SSF", rom + 0x100, 8)) { 264 uint8_t is_med_ssf = size >= 0x108 && !memcmp("SEGA SSF", rom + 0x100, 8);
265 if (is_med_ssf || (size >= 0x400000 && rom_end_raw <= 0x400000)) {
266 if (is_med_ssf && rom_end < 16*1024*1024) {
267 info->rom = rom = realloc(rom, 16*1024*1024);
268 }
263 info->mapper_start_index = 0; 269 info->mapper_start_index = 0;
264 info->mapper_type = MAPPER_SEGA; 270 info->mapper_type = is_med_ssf ? MAPPER_SEGA_MED_V2 : MAPPER_SEGA;
265 info->map_chunks = base_chunks + 9; 271 info->map_chunks = base_chunks + 9;
266 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); 272 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
267 memset(info->map, 0, sizeof(memmap_chunk)*9); 273 memset(info->map, 0, sizeof(memmap_chunk)*9);
268 memcpy(info->map+9, base_map, sizeof(memmap_chunk) * base_chunks); 274 memcpy(info->map+9, base_map, sizeof(memmap_chunk) * base_chunks);
269 275
270 info->map[0].start = 0; 276 int i;
271 info->map[0].end = 0x80000; 277 uint16_t map_flags;
272 info->map[0].mask = 0xFFFFFF; 278 if (is_med_ssf) {
273 info->map[0].flags = MMAP_READ; 279 i = 0;
274 info->map[0].buffer = rom; 280 map_flags = info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
275 281 info->save_type = RAM_FLAG_BOTH;
276 if (has_ram_header(rom, size)){ 282 info->save_size = 256*1024;
277 read_ram_header(info, rom); 283 info->save_mask = info->save_size - 1;
278 } 284 info->save_buffer = rom + 16*1024*1024 - 256*1024;
279 285 } else {
280 for (int i = 1; i < 8; i++) 286 i = 1;
287 map_flags = info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
288 info->map[0].start = 0;
289 info->map[0].end = 0x80000;
290 info->map[0].mask = 0xFFFFFF;
291 info->map[0].flags = MMAP_READ;
292 info->map[0].buffer = rom;
293
294 if (has_ram_header(rom, size)){
295 read_ram_header(info, rom);
296 }
297 }
298 static const write_8_fun med_w8[] = {
299 write_med_ram0_b,
300 write_med_ram1_b,
301 write_med_ram2_b,
302 write_med_ram3_b,
303 write_med_ram4_b,
304 write_med_ram5_b,
305 write_med_ram6_b,
306 write_med_ram7_b,
307 };
308 static const write_16_fun med_w16[] = {
309 write_med_ram0_w,
310 write_med_ram1_w,
311 write_med_ram2_w,
312 write_med_ram3_w,
313 write_med_ram4_w,
314 write_med_ram5_w,
315 write_med_ram6_w,
316 write_med_ram7_w,
317 };
318
319 for (; i < 8; i++)
281 { 320 {
282 info->map[i].start = i * 0x80000; 321 info->map[i].start = i * 0x80000;
283 info->map[i].end = (i + 1) * 0x80000; 322 info->map[i].end = (i + 1) * 0x80000;
284 info->map[i].mask = 0x7FFFF; 323 info->map[i].mask = 0x7FFFF;
285 info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom; 324 info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom;
286 info->map[i].ptr_index = i; 325 info->map[i].ptr_index = i;
287 info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL; 326 info->map[i].flags = map_flags;
288 327
289 info->map[i].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL 328 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
290 info->map[i].read_8 = (read_8_fun)read_sram_b; 329 info->map[i].read_8 = is_med_ssf ? NULL : (read_8_fun)read_sram_b;
291 info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area 330 if (is_med_ssf) {
292 info->map[i].write_8 = (write_8_fun)write_sram_area_b; 331 info->map[i].write_16 = med_w16[i];
293 332 info->map[i].write_8 = med_w8[i];
333 } else {
334 info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
335 info->map[i].write_8 = (write_8_fun)write_sram_area_b;
336 }
294 } 337 }
295 info->map[8].start = 0xA13000; 338 info->map[8].start = 0xA13000;
296 info->map[8].end = 0xA13100; 339 info->map[8].end = 0xA13100;
297 info->map[8].mask = 0xFF; 340 info->map[8].mask = 0xFF;
298 info->map[8].write_16 = (write_16_fun)write_bank_reg_w; 341 info->map[8].write_16 = (write_16_fun)write_bank_reg_w;
325 info->nor->cmd_address2 = 0x555; 368 info->nor->cmd_address2 = 0x555;
326 info->map[1].start = 0xA130C0; 369 info->map[1].start = 0xA130C0;
327 info->map[1].end = 0xA130D0; 370 info->map[1].end = 0xA130D0;
328 info->map[1].mask = 0xFFFFFF; 371 info->map[1].mask = 0xFFFFFF;
329 if (!strcmp( 372 if (!strcmp(
330 "on", 373 "on",
331 tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) 374 tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
332 ) { 375 ) {
333 info->map[1].write_16 = megawifi_write_w; 376 info->map[1].write_16 = megawifi_write_w;
334 info->map[1].write_8 = megawifi_write_b; 377 info->map[1].write_8 = megawifi_write_b;
335 info->map[1].read_16 = megawifi_read_w; 378 info->map[1].read_16 = megawifi_read_w;
386 info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL 429 info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
387 info->map[1].read_8 = (read_8_fun)read_sram_b; 430 info->map[1].read_8 = (read_8_fun)read_sram_b;
388 info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area 431 info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
389 info->map[1].write_8 = (write_8_fun)write_sram_area_b; 432 info->map[1].write_8 = (write_8_fun)write_sram_area_b;
390 info->map[1].buffer = rom + 0x200000; 433 info->map[1].buffer = rom + 0x200000;
391 434
392 //Last entry in the base map is a catch all one that needs to be 435 //Last entry in the base map is a catch all one that needs to be
393 //after all the other entries 436 //after all the other entries
394 memmap_chunk *unused = info->map + info->map_chunks - 2; 437 memmap_chunk *unused = info->map + info->map_chunks - 2;
395 memmap_chunk *last = info->map + info->map_chunks - 1; 438 memmap_chunk *last = info->map + info->map_chunks - 1;
396 *last = *unused; 439 *last = *unused;
403 last->write_8 = (write_8_fun)write_bank_reg_b; 446 last->write_8 = (write_8_fun)write_bank_reg_b;
404 } 447 }
405 return; 448 return;
406 } 449 }
407 } 450 }
408 451
409 info->map_chunks = base_chunks + 1; 452 info->map_chunks = base_chunks + 1;
410 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); 453 info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
411 memset(info->map, 0, sizeof(memmap_chunk)); 454 memset(info->map, 0, sizeof(memmap_chunk));
412 memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks); 455 memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks);
413 456
741 } else { 784 } else {
742 map->flags |= MMAP_CODE; 785 map->flags |= MMAP_CODE;
743 } 786 }
744 } else if (!strcmp(dtype, "NOR")) { 787 } else if (!strcmp(dtype, "NOR")) {
745 process_nor_def(key, state); 788 process_nor_def(key, state);
746 789
747 map->write_16 = nor_flash_write_w; 790 map->write_16 = nor_flash_write_w;
748 map->write_8 = nor_flash_write_b; 791 map->write_8 = nor_flash_write_b;
749 map->read_16 = nor_flash_read_w; 792 map->read_16 = nor_flash_read_w;
750 map->read_8 = nor_flash_read_b; 793 map->read_8 = nor_flash_read_b;
751 if (state->info->save_bus == RAM_FLAG_BOTH) { 794 if (state->info->save_bus == RAM_FLAG_BOTH) {
866 map->mask = 0xFF; 909 map->mask = 0xFF;
867 map->write_16 = write_multi_game_w; 910 map->write_16 = write_multi_game_w;
868 map->write_8 = write_multi_game_b; 911 map->write_8 = write_multi_game_b;
869 } else if (!strcmp(dtype, "megawifi")) { 912 } else if (!strcmp(dtype, "megawifi")) {
870 if (!strcmp( 913 if (!strcmp(
871 "on", 914 "on",
872 tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval) 915 tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
873 ) { 916 ) {
874 map->write_16 = megawifi_write_w; 917 map->write_16 = megawifi_write_w;
875 map->write_8 = megawifi_write_b; 918 map->write_8 = megawifi_write_b;
876 map->read_16 = megawifi_read_w; 919 map->read_16 = megawifi_read_w;
963 info.map = malloc(sizeof(memmap_chunk) * info.map_chunks); 1006 info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
964 info.eeprom_map = NULL; 1007 info.eeprom_map = NULL;
965 info.num_eeprom = 0; 1008 info.num_eeprom = 0;
966 memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); 1009 memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks);
967 map_iter_state state = { 1010 map_iter_state state = {
968 .info = &info, 1011 .info = &info,
969 .rom = rom, 1012 .rom = rom,
970 .lock_on = lock_on, 1013 .lock_on = lock_on,
971 .root = entry, 1014 .root = entry,
972 .rom_db = rom_db, 1015 .rom_db = rom_db,
973 .rom_size = rom_size, 1016 .rom_size = rom_size,
974 .lock_on_size = lock_on_size, 1017 .lock_on_size = lock_on_size,
975 .index = 0, 1018 .index = 0,
976 .num_els = info.map_chunks - base_chunks, 1019 .num_els = info.map_chunks - base_chunks,
977 .ptr_index = 0 1020 .ptr_index = 0
978 }; 1021 };
979 tern_foreach(map, map_iter_fun, &state); 1022 tern_foreach(map, map_iter_fun, &state);
980 memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks); 1023 memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);