Mercurial > repos > blastem
comparison romdb.c @ 2325:26597f9805b4
Initial Codemasters mapper support
author | Michael Pavone <pavone@retrodev.com> |
---|---|
date | Tue, 18 Jul 2023 21:46:09 -0700 |
parents | 2eda5f81f91e |
children | b9cd3c64652d |
comparison
equal
deleted
inserted
replaced
2321:2eda5f81f91e | 2325:26597f9805b4 |
---|---|
1168 return info; | 1168 return info; |
1169 } | 1169 } |
1170 | 1170 |
1171 void *sms_sega_mapper_write(uint32_t location, void *vcontext, uint8_t value); | 1171 void *sms_sega_mapper_write(uint32_t location, void *vcontext, uint8_t value); |
1172 void *sms_cart_ram_write(uint32_t location, void *vcontext, uint8_t value); | 1172 void *sms_cart_ram_write(uint32_t location, void *vcontext, uint8_t value); |
1173 void *sms_codemasters_bank0_write(uint32_t location, void *vcontext, uint8_t value); | |
1174 void *sms_codemasters_bank1_write(uint32_t location, void *vcontext, uint8_t value); | |
1175 void *sms_codemasters_bank2_write(uint32_t location, void *vcontext, uint8_t value); | |
1173 void map_iter_fun_sms(char *key, tern_val val, uint8_t valtype, void *data) | 1176 void map_iter_fun_sms(char *key, tern_val val, uint8_t valtype, void *data) |
1174 { | 1177 { |
1175 map_iter_state *state = data; | 1178 map_iter_state *state = data; |
1176 char *dtype = map_node_common(key, val, valtype, state); | 1179 char *dtype = map_node_common(key, val, valtype, state); |
1177 if (!dtype) { | 1180 if (!dtype) { |
1226 } else { | 1229 } else { |
1227 fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key); | 1230 fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key); |
1228 } | 1231 } |
1229 } | 1232 } |
1230 | 1233 |
1234 uint8_t has_codemasters_header(uint8_t *rom, uint32_t rom_size) | |
1235 { | |
1236 if (rom_size < 0x8000) { | |
1237 return 0; | |
1238 } | |
1239 //Date and time fields should be valid BCD | |
1240 for (uint32_t i = 0x7FE1; i < 0x7FE6; i++) | |
1241 { | |
1242 if ((rom[i] & 0xF0) > 0x90) { | |
1243 return 0; | |
1244 } | |
1245 if ((rom[i] & 0xF) > 0x9) { | |
1246 return 0; | |
1247 } | |
1248 } | |
1249 uint16_t checksum = rom[0x7FE6] | rom[0x7FE7] << 8; | |
1250 uint16_t complement = rom[0x7FE8] | rom[0x7FE9] << 8; | |
1251 if (complement != (0x10000 - checksum)) { | |
1252 return 0; | |
1253 } | |
1254 puts("Detected codemasters mapper"); | |
1255 return 1; | |
1256 } | |
1257 | |
1231 void sms_memmap_heuristics(rom_info *info, memmap_chunk const *base_map, uint32_t num_base_chunks) | 1258 void sms_memmap_heuristics(rom_info *info, memmap_chunk const *base_map, uint32_t num_base_chunks) |
1232 { | 1259 { |
1233 uint32_t num_chunks = num_base_chunks + (info->rom_size > 0xC000 ? 5 : 1); | 1260 uint32_t num_chunks = num_base_chunks + (info->rom_size > 0xC000 ? 5 : 1); |
1234 memmap_chunk *chunks = calloc(num_chunks, sizeof(memmap_chunk)); | 1261 memmap_chunk *chunks = calloc(num_chunks, sizeof(memmap_chunk)); |
1235 info->map = chunks; | 1262 info->map = chunks; |
1236 info->map_chunks = num_chunks; | 1263 info->map_chunks = num_chunks; |
1237 if (info->rom_size > 0xC000) { | 1264 if (info->rom_size > 0xC000) { |
1238 //TODO: codemasters header | 1265 if (has_codemasters_header(info->rom, info->rom_size)) { |
1239 info->mapper_type = MAPPER_SMS_SEGA; | 1266 info->mapper_type = MAPPER_SMS_CODEMASTERS; |
1240 memcpy(chunks + 4, base_map, sizeof(memmap_chunk) * num_base_chunks); | 1267 memcpy(chunks + 3, base_map, sizeof(memmap_chunk) * num_base_chunks); |
1241 chunks[0].start = 0; | 1268 num_chunks--; |
1242 chunks[0].end = 0x400; | 1269 chunks[0].start = 0; |
1243 chunks[0].mask = 0xFFFF; | 1270 chunks[0].end = 0x4000; |
1244 chunks[0].flags = MMAP_READ; | 1271 chunks[0].mask = 0x3FFF; |
1245 chunks[0].buffer = info->rom; | 1272 chunks[0].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; |
1246 chunks[1].start = 0x400; | 1273 chunks[0].ptr_index = 0; |
1247 chunks[1].end = 0x4000; | 1274 chunks[0].write_8 = sms_codemasters_bank0_write; |
1248 chunks[1].mask = 0x3FFF; | 1275 chunks[1].start = 0x4000; |
1249 chunks[1].ptr_index = 0; | 1276 chunks[1].end = 0x8000; |
1250 chunks[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | 1277 chunks[1].mask = 0x3FFF; |
1251 chunks[2].start = 0x4000; | 1278 chunks[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; |
1252 chunks[2].end = 0x8000; | 1279 chunks[1].ptr_index = 1; |
1253 chunks[2].mask = 0x3FFF; | 1280 chunks[1].write_8 = sms_codemasters_bank1_write; |
1254 chunks[2].ptr_index = 1; | 1281 chunks[2].start = 0x8000; |
1255 chunks[2].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | 1282 chunks[2].end = 0xC000; |
1256 chunks[3].start = 0x8000; | 1283 chunks[2].mask = 0x3FFF; |
1257 chunks[3].end = 0xC000; | 1284 chunks[2].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; |
1258 chunks[3].mask = 0x3FFF; | 1285 chunks[2].ptr_index = 2; |
1259 chunks[3].ptr_index = 2; | 1286 chunks[2].write_8 = sms_codemasters_bank2_write; |
1260 chunks[3].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | 1287 } else { |
1261 chunks[3].write_8 = sms_cart_ram_write; | 1288 info->mapper_type = MAPPER_SMS_SEGA; |
1262 chunks[num_chunks - 1].start = 0xFFFC; | 1289 memcpy(chunks + 4, base_map, sizeof(memmap_chunk) * num_base_chunks); |
1263 chunks[num_chunks - 1].end = 0x10000; | 1290 chunks[0].start = 0; |
1264 chunks[num_chunks - 1].mask = 3; | 1291 chunks[0].end = 0x400; |
1265 chunks[num_chunks - 1].flags = MMAP_READ; | 1292 chunks[0].mask = 0xFFFF; |
1266 chunks[num_chunks - 1].write_8 = sms_sega_mapper_write; | 1293 chunks[0].flags = MMAP_READ; |
1267 for (uint32_t i = 4; i < num_chunks - 1; i++) | 1294 chunks[0].buffer = info->rom; |
1268 { | 1295 chunks[1].start = 0x400; |
1269 if (chunks[i].end > 0xFFFC) { | 1296 chunks[1].end = 0x4000; |
1270 //mapper regs overlap RAM from base map | 1297 chunks[1].mask = 0x3FFF; |
1271 chunks[i].end = 0xFFFC; | 1298 chunks[1].ptr_index = 0; |
1299 chunks[1].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | |
1300 chunks[2].start = 0x4000; | |
1301 chunks[2].end = 0x8000; | |
1302 chunks[2].mask = 0x3FFF; | |
1303 chunks[2].ptr_index = 1; | |
1304 chunks[2].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | |
1305 chunks[3].start = 0x8000; | |
1306 chunks[3].end = 0xC000; | |
1307 chunks[3].mask = 0x3FFF; | |
1308 chunks[3].ptr_index = 2; | |
1309 chunks[3].flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE; | |
1310 chunks[3].write_8 = sms_cart_ram_write; | |
1311 chunks[num_chunks - 1].start = 0xFFFC; | |
1312 chunks[num_chunks - 1].end = 0x10000; | |
1313 chunks[num_chunks - 1].mask = 3; | |
1314 chunks[num_chunks - 1].flags = MMAP_READ; | |
1315 chunks[num_chunks - 1].write_8 = sms_sega_mapper_write; | |
1316 for (uint32_t i = 4; i < num_chunks - 1; i++) | |
1317 { | |
1318 if (chunks[i].end > 0xFFFC) { | |
1319 //mapper regs overlap RAM from base map | |
1320 chunks[i].end = 0xFFFC; | |
1321 } | |
1272 } | 1322 } |
1273 } | 1323 } |
1274 } else { | 1324 } else { |
1275 info->mapper_type = MAPPER_NONE; | 1325 info->mapper_type = MAPPER_NONE; |
1276 memcpy(chunks + 1, base_map, sizeof(memmap_chunk) * num_base_chunks); | 1326 memcpy(chunks + 1, base_map, sizeof(memmap_chunk) * num_base_chunks); |