comparison romdb.c @ 768:2f48a3c187c6

Add support for reading cartridge memory map from ROM database, though without EEPROM support for now
author Michael Pavone <pavone@retrodev.com>
date Tue, 07 Jul 2015 19:33:33 -0700
parents ea525f600b1d
children 4638b88bc72d
comparison
equal deleted inserted replaced
767:ea525f600b1d 768:2f48a3c187c6
205 } 205 }
206 206
207 uint32_t get_u32be(uint8_t *data) 207 uint32_t get_u32be(uint8_t *data)
208 { 208 {
209 return *data << 24 | data[1] << 16 | data[2] << 8 | data[3]; 209 return *data << 24 | data[1] << 16 | data[2] << 8 | data[3];
210 }
211
212 uint32_t calc_mask(uint32_t src_size, uint32_t start, uint32_t end)
213 {
214 uint32_t map_size = end-start+1;
215 if (src_size < map_size) {
216 return nearest_pow2(src_size)-1;
217 } else if (!start) {
218 return 0xFFFFFF;
219 } else {
220 return nearest_pow2(map_size)-1;
221 }
210 } 222 }
211 223
212 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) 224 void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks)
213 { 225 {
214 if (rom[RAM_ID] == 'R' && rom[RAM_ID+1] == 'A') { 226 if (rom[RAM_ID] == 'R' && rom[RAM_ID+1] == 'A') {
296 info.regions = get_header_regions(rom); 308 info.regions = get_header_regions(rom);
297 add_memmap_header(&info, rom, rom_size, base_map, base_chunks); 309 add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
298 return info; 310 return info;
299 } 311 }
300 312
313 typedef struct {
314 rom_info *info;
315 uint8_t *rom;
316 tern_node *root;
317 uint32_t rom_size;
318 int index;
319 } map_iter_state;
320
321 void map_iter_fun(char *key, tern_val val, void *data)
322 {
323 map_iter_state *state = data;
324 tern_node *node = tern_get_node(val);
325 if (!node) {
326 fprintf(stderr, "ROM DB map entry %d with address %s is not a node\n", state->index, key);
327 exit(1);
328 }
329 uint32_t start = strtol(key, NULL, 16);
330 uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16);
331 if (!end || end < start) {
332 fprintf(stderr, "'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key);
333 exit(1);
334 }
335 char * dtype = tern_find_ptr_default(node, "device", "ROM");
336 uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 0);
337 memmap_chunk *map = state->info->map + state->index;
338 map->start = start;
339 map->end = end;
340 if (!strcmp(dtype, "ROM")) {
341 map->buffer = state->rom + offset;
342 map->flags = MMAP_READ;
343 map->mask = calc_mask(state->rom_size, start, end);
344 } else if (!strcmp(dtype, "EEPROM")) {
345
346
347 } else if (!strcmp(dtype, "SRAM")) {
348 if (!state->info->save_size) {
349 char * size = tern_find_path(state->root, "SRAM\0size\0").ptrval;
350 if (!size) {
351 fprintf(stderr, "ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key);
352 exit(1);
353 }
354 state->info->save_size = atoi(size);
355 if (!state->info->save_size) {
356 fprintf(stderr, "SRAM size %s is invalid\n", size);
357 exit(1);
358 }
359 state->info->save_buffer = malloc(state->info->save_size);
360 char *bus = tern_find_path(state->root, "SRAM\0bus\0").ptrval;
361 if (!strcmp(bus, "odd")) {
362 state->info->save_type = RAM_FLAG_ODD;
363 } else if(!strcmp(bus, "even")) {
364 state->info->save_type = RAM_FLAG_EVEN;
365 } else {
366 state->info->save_type = RAM_FLAG_BOTH;
367 }
368 }
369 map->buffer = state->info->save_buffer + offset;
370 map->flags = MMAP_READ | MMAP_WRITE;
371 if (state->info->save_type == RAM_FLAG_ODD) {
372 map->flags |= MMAP_ONLY_ODD;
373 } else if(state->info->save_type == RAM_FLAG_EVEN) {
374 map->flags |= MMAP_ONLY_EVEN;
375 }
376 map->mask = calc_mask(state->info->save_size, start, end);
377 } else {
378 fprintf(stderr, "Invalid device type for ROM DB map entry %d with address %s\n", state->index, key);
379 exit(1);
380 }
381 state->index++;
382 }
383
301 rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks) 384 rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
302 { 385 {
303 uint8_t product_id[GAME_ID_LEN+1]; 386 uint8_t product_id[GAME_ID_LEN+1];
304 uint8_t *rom = vrom; 387 uint8_t *rom = vrom;
305 product_id[GAME_ID_LEN] = 0; 388 product_id[GAME_ID_LEN] = 0;
310 break; 393 break;
311 } 394 }
312 product_id[i] = rom[GAME_ID_OFF + i]; 395 product_id[i] = rom[GAME_ID_OFF + i];
313 396
314 } 397 }
315 tern_node * entry = tern_find_prefix(rom_db, product_id); 398 printf("Product ID: %s\n", product_id);
399 tern_node * entry = tern_find_ptr(rom_db, product_id);
316 if (!entry) { 400 if (!entry) {
401 puts("Not found in ROM DB, examining header\n");
317 return configure_rom_heuristics(rom, rom_size, base_map, base_chunks); 402 return configure_rom_heuristics(rom, rom_size, base_map, base_chunks);
318 } 403 }
319 rom_info info; 404 rom_info info;
320 info.name = tern_find_ptr(entry, "name"); 405 info.name = tern_find_ptr(entry, "name");
321 if (info.name) { 406 if (info.name) {
407 printf("Found name: %s\n", info.name);
322 info.name = strdup(info.name); 408 info.name = strdup(info.name);
323 } else { 409 } else {
324 info.name = get_header_name(rom); 410 info.name = get_header_name(rom);
325 } 411 }
326 412
334 } 420 }
335 if (!info.regions) { 421 if (!info.regions) {
336 info.regions = get_header_regions(rom); 422 info.regions = get_header_regions(rom);
337 } 423 }
338 424
339 tern_node *map = tern_find_prefix(entry, "map"); 425 tern_node *map = tern_find_ptr(entry, "map");
340 if (map) { 426 if (map) {
341 uint32_t map_count = tern_count(map); 427 info.map_chunks = tern_count(map);
342 if (map_count) { 428 if (info.map_chunks) {
343 429 info.map_chunks += base_chunks;
430 info.save_buffer = NULL;
431 info.save_size = 0;
432 info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
433 memset(info.map, 0, sizeof(memmap_chunk) * (info.map_chunks - base_chunks));
434 map_iter_state state = {&info, rom, entry, rom_size, 0};
435 tern_foreach(map, map_iter_fun, &state);
436 memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);
344 } else { 437 } else {
345 add_memmap_header(&info, rom, rom_size, base_map, base_chunks); 438 add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
346 } 439 }
347 } else { 440 } else {
348 add_memmap_header(&info, rom, rom_size, base_map, base_chunks); 441 add_memmap_header(&info, rom, rom_size, base_map, base_chunks);