Mercurial > repos > blastem
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); |