summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--rom.db28
-rw-r--r--romdb.c103
-rw-r--r--tern.c8
-rw-r--r--tern.h1
-rw-r--r--util.c11
-rw-r--r--util.h2
6 files changed, 132 insertions, 21 deletions
diff --git a/rom.db b/rom.db
index a31ef0a..bc9eea2 100644
--- a/rom.db
+++ b/rom.db
@@ -1,6 +1,6 @@
T-081326 {
name NBA Jam
- eeprom {
+ EEPROM {
type i2c
size 256
}
@@ -10,7 +10,7 @@ T-081326 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
1 sda
@@ -24,7 +24,7 @@ T-081326 {
}
T-81033 {
name NBA Jam
- eeprom {
+ EEPROM {
type i2c
size 256
}
@@ -34,7 +34,7 @@ T-81033 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
1 sda
@@ -48,7 +48,7 @@ T-81033 {
}
T-081276 {
name NFL Quarterback Club
- eeprom {
+ EEPROM {
type i2c
size 256
}
@@ -58,7 +58,7 @@ T-081276 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
0 sda
@@ -72,7 +72,7 @@ T-081276 {
}
T-81406 {
name NBA Jam TE
- eeprom {
+ EEPROM {
type i2c
size 512
}
@@ -82,7 +82,7 @@ T-81406 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
0 sda
@@ -96,7 +96,7 @@ T-81406 {
}
T-081586 {
name NFL Quarterback Club '96
- eeprom {
+ EEPROM {
type i2c
size 2048
}
@@ -106,7 +106,7 @@ T-081586 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
0 sda
@@ -120,7 +120,7 @@ T-081586 {
}
T-81576 {
name College Slam
- eeprom {
+ EEPROM {
type i2c
size 8192
}
@@ -130,7 +130,7 @@ T-81576 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
0 sda
@@ -144,7 +144,7 @@ T-81576 {
}
T-81476 {
name Frank Thomas Big Hurt Baseball
- eeprom {
+ EEPROM {
type i2c
size 8192
}
@@ -154,7 +154,7 @@ T-81476 {
last 1FFFFF
}
200000 {
- device eeprom
+ device EEPROM
last 3FFFFF
bits_read {
0 sda
diff --git a/romdb.c b/romdb.c
index c22ec4d..bcd8c7b 100644
--- a/romdb.c
+++ b/romdb.c
@@ -209,6 +209,18 @@ uint32_t get_u32be(uint8_t *data)
return *data << 24 | data[1] << 16 | data[2] << 8 | data[3];
}
+uint32_t calc_mask(uint32_t src_size, uint32_t start, uint32_t end)
+{
+ uint32_t map_size = end-start+1;
+ if (src_size < map_size) {
+ return nearest_pow2(src_size)-1;
+ } else if (!start) {
+ return 0xFFFFFF;
+ } else {
+ return nearest_pow2(map_size)-1;
+ }
+}
+
void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks)
{
if (rom[RAM_ID] == 'R' && rom[RAM_ID+1] == 'A') {
@@ -298,6 +310,77 @@ rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk
return info;
}
+typedef struct {
+ rom_info *info;
+ uint8_t *rom;
+ tern_node *root;
+ uint32_t rom_size;
+ int index;
+} map_iter_state;
+
+void map_iter_fun(char *key, tern_val val, void *data)
+{
+ map_iter_state *state = data;
+ tern_node *node = tern_get_node(val);
+ if (!node) {
+ fprintf(stderr, "ROM DB map entry %d with address %s is not a node\n", state->index, key);
+ exit(1);
+ }
+ uint32_t start = strtol(key, NULL, 16);
+ uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16);
+ if (!end || end < start) {
+ fprintf(stderr, "'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key);
+ exit(1);
+ }
+ char * dtype = tern_find_ptr_default(node, "device", "ROM");
+ uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 0);
+ memmap_chunk *map = state->info->map + state->index;
+ map->start = start;
+ map->end = end;
+ if (!strcmp(dtype, "ROM")) {
+ map->buffer = state->rom + offset;
+ map->flags = MMAP_READ;
+ map->mask = calc_mask(state->rom_size, start, end);
+ } else if (!strcmp(dtype, "EEPROM")) {
+
+
+ } else if (!strcmp(dtype, "SRAM")) {
+ if (!state->info->save_size) {
+ char * size = tern_find_path(state->root, "SRAM\0size\0").ptrval;
+ if (!size) {
+ 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);
+ exit(1);
+ }
+ state->info->save_size = atoi(size);
+ if (!state->info->save_size) {
+ fprintf(stderr, "SRAM size %s is invalid\n", size);
+ exit(1);
+ }
+ state->info->save_buffer = malloc(state->info->save_size);
+ char *bus = tern_find_path(state->root, "SRAM\0bus\0").ptrval;
+ if (!strcmp(bus, "odd")) {
+ state->info->save_type = RAM_FLAG_ODD;
+ } else if(!strcmp(bus, "even")) {
+ state->info->save_type = RAM_FLAG_EVEN;
+ } else {
+ state->info->save_type = RAM_FLAG_BOTH;
+ }
+ }
+ map->buffer = state->info->save_buffer + offset;
+ map->flags = MMAP_READ | MMAP_WRITE;
+ if (state->info->save_type == RAM_FLAG_ODD) {
+ map->flags |= MMAP_ONLY_ODD;
+ } else if(state->info->save_type == RAM_FLAG_EVEN) {
+ map->flags |= MMAP_ONLY_EVEN;
+ }
+ map->mask = calc_mask(state->info->save_size, start, end);
+ } else {
+ fprintf(stderr, "Invalid device type for ROM DB map entry %d with address %s\n", state->index, key);
+ exit(1);
+ }
+ state->index++;
+}
+
rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
{
uint8_t product_id[GAME_ID_LEN+1];
@@ -312,13 +395,16 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_
product_id[i] = rom[GAME_ID_OFF + i];
}
- tern_node * entry = tern_find_prefix(rom_db, product_id);
+ printf("Product ID: %s\n", product_id);
+ tern_node * entry = tern_find_ptr(rom_db, product_id);
if (!entry) {
+ puts("Not found in ROM DB, examining header\n");
return configure_rom_heuristics(rom, rom_size, base_map, base_chunks);
}
rom_info info;
info.name = tern_find_ptr(entry, "name");
if (info.name) {
+ printf("Found name: %s\n", info.name);
info.name = strdup(info.name);
} else {
info.name = get_header_name(rom);
@@ -336,11 +422,18 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_
info.regions = get_header_regions(rom);
}
- tern_node *map = tern_find_prefix(entry, "map");
+ tern_node *map = tern_find_ptr(entry, "map");
if (map) {
- uint32_t map_count = tern_count(map);
- if (map_count) {
-
+ info.map_chunks = tern_count(map);
+ if (info.map_chunks) {
+ info.map_chunks += base_chunks;
+ info.save_buffer = NULL;
+ info.save_size = 0;
+ info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
+ memset(info.map, 0, sizeof(memmap_chunk) * (info.map_chunks - base_chunks));
+ map_iter_state state = {&info, rom, entry, rom_size, 0};
+ tern_foreach(map, map_iter_fun, &state);
+ memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);
} else {
add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
}
diff --git a/tern.c b/tern.c
index 2929bd6..e4f80f8 100644
--- a/tern.c
+++ b/tern.c
@@ -107,7 +107,11 @@ void * tern_find_ptr_default(tern_node * head, char * key, void * def)
{
tern_val ret;
if (tern_find(head, key, &ret)) {
- return ret.ptrval;
+ if (ret.intval & 1) {
+ return (void *)(ret.intval & ~1);
+ } else {
+ return ret.ptrval;
+ }
}
return def;
}
@@ -193,7 +197,7 @@ void tern_foreach_int(tern_node *head, iter_fun fun, void *data, char *keybuf, i
tern_foreach_int(head->straight.next, fun, data, keybuf, pos+1);
}
if (head->right) {
- tern_foreach_int(head->left, fun, data, keybuf, pos);
+ tern_foreach_int(head->right, fun, data, keybuf, pos);
}
}
diff --git a/tern.h b/tern.h
index c708110..5c0dcfd 100644
--- a/tern.h
+++ b/tern.h
@@ -39,6 +39,7 @@ tern_val tern_find_path(tern_node *head, char *key);
tern_node * tern_insert_ptr(tern_node * head, char * key, void * value);
tern_node * tern_insert_node(tern_node *head, char *key, tern_node *value);
uint32_t tern_count(tern_node *head);
+void tern_foreach(tern_node *head, iter_fun fun, void *data);
char * tern_int_key(uint32_t key, char * buf);
tern_node * tern_get_node(tern_val value);
diff --git a/util.c b/util.c
index 20aa2ee..361d26b 100644
--- a/util.c
+++ b/util.c
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
+#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -68,6 +69,16 @@ char * split_keyval(char * text)
return text+1;
}
+uint32_t nearest_pow2(uint32_t val)
+{
+ uint32_t ret = 1;
+ while (ret < val)
+ {
+ ret = ret << 1;
+ }
+ return ret;
+}
+
static char * exe_str;
void set_exe_str(char * str)
diff --git a/util.h b/util.h
index 780f538..85b0c8f 100644
--- a/util.h
+++ b/util.h
@@ -15,6 +15,8 @@ long file_size(FILE * f);
char * strip_ws(char * text);
//Inserts a null after the first word, returns a pointer to the second word
char * split_keyval(char * text);
+//Gets the smallest power of two that is >= a certain value, won't work for values > 0x80000000
+uint32_t nearest_pow2(uint32_t val);
//Should be called by main with the value of argv[0] for use by get_exe_dir
void set_exe_str(char * str);
//Returns the directory the executable is in