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);