From 8f0979a2c4db824e91ead3290d8088d97b20e189 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 2 Jul 2015 19:19:06 -0700 Subject: Initial work on ROM database --- romdb.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 romdb.c (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c new file mode 100644 index 0000000..0de4af5 --- /dev/null +++ b/romdb.c @@ -0,0 +1,83 @@ +#include +#include +#include "config.h" +#include "romdb.h" +#include "util.h" + +#define GAME_ID_OFF 0x183 +#define GAME_ID_LEN 8 +#define TITLE_START 0x150 +#define TITLE_END (TITLE_START+48) + +tern_node *load_rom_db() +{ + char *exe_dir = get_exe_dir(); + if (!exe_dir) { + fputs("Failed to find executable path\n", stderr); + exit(1); + } + char *path = alloc_concat(exe_dir, "/rom.db"); + tern_node *db = parse_config_file(path); + free(path); + if (!db) { + fputs("Failed to load ROM DB\n", stderr); + } + return db; +} + +char *get_header_name(uint8_t *rom) +{ + uint8_t *last = rom + TITLE_END - 1; + uint8_t *src = rom + TITLE_START; + + while (last > src && (*last <= 0x20 || *last >= 0x80)) + { + last--; + } + if (last == src) { + //TODO: Use other name field + return strdup("UNKNOWN"); + } else { + last++; + char *ret = malloc(last - (rom + TITLE_START) + 1); + uint8_t *dst; + for (dst = ret; src < last; src++) + { + if (*src >= 0x20 && *src < 0x80) { + *(dst++) = *src; + } + } + *dst = 0; + return ret; + } +} + +rom_info configure_rom_heuristics(uint8_t *rom) +{ + rom_info info; + info.name = get_header_name(rom); + +} + +rom_info configure_rom(tern_node *rom_db, void *vrom) +{ + uint8_t product_id[GAME_ID_LEN+1]; + uint8_t *rom = vrom; + product_id[GAME_ID_LEN] = 0; + for (int i = 0; i < GAME_ID_LEN; i++) + { + if (rom[GAME_ID_OFF + i] <= ' ') { + product_id[i] = 0; + break; + } + product_id[i] = rom[GAME_ID_OFF + i]; + + } + tern_node * entry = tern_find_prefix(rom_db, product_id); + if (!entry) { + return configure_rom_heuristics(rom); + } + rom_info info; + info.name = strdup(tern_find_ptr_default(entry, "name", "UNKNOWN")); + return info; +} \ No newline at end of file -- cgit v1.2.3 From 249115277c7f488052e07ccbd91f0df9f24f26b7 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Thu, 2 Jul 2015 20:43:01 -0700 Subject: Allow regions to be set in ROM DB. Prefer default region if it is one of the valid regions for the ROM. --- romdb.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 5 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 0de4af5..fbfcef9 100644 --- a/romdb.c +++ b/romdb.c @@ -4,10 +4,11 @@ #include "romdb.h" #include "util.h" -#define GAME_ID_OFF 0x183 -#define GAME_ID_LEN 8 #define TITLE_START 0x150 #define TITLE_END (TITLE_START+48) +#define GAME_ID_OFF 0x183 +#define GAME_ID_LEN 8 +#define REGION_START 0x1F0 tern_node *load_rom_db() { @@ -52,11 +53,37 @@ char *get_header_name(uint8_t *rom) } } +char *region_chars = "UB4JEA"; +uint8_t region_bits[] = {REGION_U, REGION_U, REGION_U, REGION_J, REGION_E, REGION_E}; + +uint8_t translate_region_char(uint8_t c) +{ + for (int i = 0; i < sizeof(region_bits); i++) + { + if (c == region_chars[i]) { + return region_bits[i]; + } + } + return 0; +} + +uint8_t get_header_regions(uint8_t *rom) +{ + uint8_t regions = 0; + for (int i = 0; i < 3; i++) + { + regions |= translate_region_char(rom[REGION_START + i]); + } + return regions; +} + + rom_info configure_rom_heuristics(uint8_t *rom) { rom_info info; info.name = get_header_name(rom); - + info.regions = get_header_regions(rom); + return info; } rom_info configure_rom(tern_node *rom_db, void *vrom) @@ -78,6 +105,23 @@ rom_info configure_rom(tern_node *rom_db, void *vrom) return configure_rom_heuristics(rom); } rom_info info; - info.name = strdup(tern_find_ptr_default(entry, "name", "UNKNOWN")); + info.name = tern_find_ptr(entry, "name"); + if (info.name) { + info.name = strdup(info.name); + } else { + info.name = get_header_name(rom); + } + + char *dbreg = tern_find_ptr(entry, "regions"); + info.regions = 0; + if (dbreg) { + while (*dbreg != 0) + { + info.regions |= translate_region_char(*(dbreg++)); + } + } + if (!info.regions) { + info.regions = get_header_regions(rom); + } return info; -} \ No newline at end of file +} -- cgit v1.2.3 From 0be7e726ad839d36d50db630b24ea0f1dc141c08 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 5 Jul 2015 14:21:34 -0700 Subject: WIP changes to support reading cart memory map from ROM DB --- romdb.c | 226 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 223 insertions(+), 3 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index fbfcef9..fce0c84 100644 --- a/romdb.c +++ b/romdb.c @@ -3,13 +3,140 @@ #include "config.h" #include "romdb.h" #include "util.h" +#include "blastem.h" #define TITLE_START 0x150 #define TITLE_END (TITLE_START+48) #define GAME_ID_OFF 0x183 #define GAME_ID_LEN 8 +#define ROM_END 0x1A4 +#define RAM_ID 0x1B0 +#define RAM_FLAGS 0x1B2 +#define RAM_START 0x1B4 +#define RAM_END 0x1B8 #define REGION_START 0x1F0 +uint16_t read_sram_w(uint32_t address, m68k_context * context) +{ + genesis_context * gen = context->system; + address &= gen->save_ram_mask; + switch(gen->save_flags) + { + case RAM_FLAG_BOTH: + return gen->save_ram[address] << 8 | gen->save_ram[address+1]; + case RAM_FLAG_EVEN: + return gen->save_ram[address >> 1] << 8 | 0xFF; + case RAM_FLAG_ODD: + return gen->save_ram[address >> 1] | 0xFF00; + } + return 0xFFFF;//We should never get here +} + +uint8_t read_sram_b(uint32_t address, m68k_context * context) +{ + genesis_context * gen = context->system; + address &= gen->save_ram_mask; + switch(gen->save_flags) + { + case RAM_FLAG_BOTH: + return gen->save_ram[address]; + case RAM_FLAG_EVEN: + if (address & 1) { + return 0xFF; + } else { + return gen->save_ram[address >> 1]; + } + case RAM_FLAG_ODD: + if (address & 1) { + return gen->save_ram[address >> 1]; + } else { + return 0xFF; + } + } + return 0xFF;//We should never get here +} + +m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value) +{ + genesis_context * gen = context->system; + if ((gen->bank_regs[0] & 0x3) == 1) { + address &= gen->save_ram_mask; + switch(gen->save_flags) + { + case RAM_FLAG_BOTH: + gen->save_ram[address] = value >> 8; + gen->save_ram[address+1] = value; + break; + case RAM_FLAG_EVEN: + gen->save_ram[address >> 1] = value >> 8; + break; + case RAM_FLAG_ODD: + gen->save_ram[address >> 1] = value; + break; + } + } + return context; +} + +m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8_t value) +{ + genesis_context * gen = context->system; + if ((gen->bank_regs[0] & 0x3) == 1) { + address &= gen->save_ram_mask; + switch(gen->save_flags) + { + case RAM_FLAG_BOTH: + gen->save_ram[address] = value; + break; + case RAM_FLAG_EVEN: + if (!(address & 1)) { + gen->save_ram[address >> 1] = value; + } + break; + case RAM_FLAG_ODD: + if (address & 1) { + gen->save_ram[address >> 1] = value; + } + break; + } + } + return context; +} + +m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value) +{ + genesis_context * gen = context->system; + address &= 0xE; + address >>= 1; + gen->bank_regs[address] = value; + if (!address) { + if (value & 1) { + context->mem_pointers[2] = NULL; + } else { + context->mem_pointers[2] = cart + 0x200000/2; + } + } + return context; +} + +m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value) +{ + if (address & 1) { + genesis_context * gen = context->system; + address &= 0xE; + address >>= 1; + gen->bank_regs[address] = value; + if (!address) { + if (value & 1) { + context->mem_pointers[2] = NULL; + } else { + context->mem_pointers[2] = cart + 0x200000/2; + } + } + } + return context; +} + tern_node *load_rom_db() { char *exe_dir = get_exe_dir(); @@ -77,16 +204,96 @@ uint8_t get_header_regions(uint8_t *rom) return regions; } +uint32_t get_u32be(uint8_t *data) +{ + return *data << 24 | data[1] << 16 | data[2] << 8 | data[3]; +} + +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') { + uint32_t rom_end = get_u32be(rom + ROM_END) + 1; + uint32_t ram_start = get_u32be(rom + RAM_START); + uint32_t ram_end = get_u32be(rom + RAM_END); + uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK; + ram_start &= 0xFFFFFE; + ram_end |= 1; + + info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3); + info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); + memset(info->map, 0, sizeof(memmap_chunk)*2); + memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks); + + if (ram_start >= rom_end) { + info->map[0].end = rom_end; + //TODO: ROM mirroring + info->map[0].mask = 0xFFFFFF; + info->map[0].flags = MMAP_READ; + info->map[0].buffer = rom; + + info->map[1].start = ram_start; + info->map[1].mask = ram_end - ram_start; + info->map[1].end = ram_end + 1; + info->map[1].flags = MMAP_READ | MMAP_WRITE; + uint32_t size = info->map[1].mask + 1; + if (ram_flags == RAM_FLAG_ODD) { + info->map[1].flags |= MMAP_ONLY_ODD; + size /= 2; + } else if (ram_flags == RAM_FLAG_EVEN) { + info->map[1].flags |= MMAP_ONLY_EVEN; + size /= 2; + } + info->map[1].buffer = malloc(size); + } else { + //Assume the standard Sega mapper + info->map[0].end = 0x200000; + info->map[0].mask = 0xFFFFFF; + info->map[0].flags = MMAP_READ; + info->map[0].buffer = rom; + + info->map[1].start = 0x200000; + info->map[1].end = 0x400000; + info->map[1].mask = 0x1FFFFF; + info->map[1].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL; + info->map[1].ptr_index = 2; + info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL + info->map[1].read_8 = (read_8_fun)read_sram_b; + info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area + info->map[1].write_8 = (write_8_fun)write_sram_area_b; + info->map[1].buffer = cart + 0x200000; + + memmap_chunk *last = info->map + info->map_chunks - 1; + memset(last, 0, sizeof(memmap_chunk)); + last->start = 0xA13000; + last->end = 0xA13100; + last->mask = 0xFF; + last->write_16 = (write_16_fun)write_bank_reg_w; + last->write_8 = (write_8_fun)write_bank_reg_b; + } + } else { + info->map_chunks = base_chunks + 1; + info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); + memset(info->map, 0, sizeof(memmap_chunk)); + memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks); + + info->map[0].end = 0x400000; + info->map[0].mask = 0xFFFFFF; + info->map[0].flags = MMAP_READ; + info->map[0].buffer = rom; + info->save_type = SAVE_NONE; + } +} -rom_info configure_rom_heuristics(uint8_t *rom) +rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks) { rom_info info; info.name = get_header_name(rom); info.regions = get_header_regions(rom); + add_memmap_header(&info, rom, rom_size, base_map, base_chunks); return info; } -rom_info configure_rom(tern_node *rom_db, void *vrom) +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]; uint8_t *rom = vrom; @@ -102,7 +309,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom) } tern_node * entry = tern_find_prefix(rom_db, product_id); if (!entry) { - return configure_rom_heuristics(rom); + return configure_rom_heuristics(rom, rom_size, base_map, base_chunks); } rom_info info; info.name = tern_find_ptr(entry, "name"); @@ -123,5 +330,18 @@ rom_info configure_rom(tern_node *rom_db, void *vrom) if (!info.regions) { info.regions = get_header_regions(rom); } + + tern_node *map = tern_find_prefix(entry, "map"); + if (map) { + uint32_t map_count = tern_count(map); + if (map_count) { + + } else { + add_memmap_header(&info, rom, rom_size, base_map, base_chunks); + } + } else { + add_memmap_header(&info, rom, rom_size, base_map, base_chunks); + } + return info; } -- cgit v1.2.3 From 358991e7fef42ae206231aabfeee045e5214dbe4 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 6 Jul 2015 19:46:46 -0700 Subject: SRAM detection from ROM header is no working correctly again --- romdb.c | 49 +++++++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index fce0c84..c22ec4d 100644 --- a/romdb.c +++ b/romdb.c @@ -20,14 +20,14 @@ uint16_t read_sram_w(uint32_t address, m68k_context * context) { genesis_context * gen = context->system; address &= gen->save_ram_mask; - switch(gen->save_flags) + switch(gen->save_type) { case RAM_FLAG_BOTH: - return gen->save_ram[address] << 8 | gen->save_ram[address+1]; + return gen->save_storage[address] << 8 | gen->save_storage[address+1]; case RAM_FLAG_EVEN: - return gen->save_ram[address >> 1] << 8 | 0xFF; + return gen->save_storage[address >> 1] << 8 | 0xFF; case RAM_FLAG_ODD: - return gen->save_ram[address >> 1] | 0xFF00; + return gen->save_storage[address >> 1] | 0xFF00; } return 0xFFFF;//We should never get here } @@ -36,19 +36,19 @@ uint8_t read_sram_b(uint32_t address, m68k_context * context) { genesis_context * gen = context->system; address &= gen->save_ram_mask; - switch(gen->save_flags) + switch(gen->save_type) { case RAM_FLAG_BOTH: - return gen->save_ram[address]; + return gen->save_storage[address]; case RAM_FLAG_EVEN: if (address & 1) { return 0xFF; } else { - return gen->save_ram[address >> 1]; + return gen->save_storage[address >> 1]; } case RAM_FLAG_ODD: if (address & 1) { - return gen->save_ram[address >> 1]; + return gen->save_storage[address >> 1]; } else { return 0xFF; } @@ -61,17 +61,17 @@ m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint1 genesis_context * gen = context->system; if ((gen->bank_regs[0] & 0x3) == 1) { address &= gen->save_ram_mask; - switch(gen->save_flags) + switch(gen->save_type) { case RAM_FLAG_BOTH: - gen->save_ram[address] = value >> 8; - gen->save_ram[address+1] = value; + gen->save_storage[address] = value >> 8; + gen->save_storage[address+1] = value; break; case RAM_FLAG_EVEN: - gen->save_ram[address >> 1] = value >> 8; + gen->save_storage[address >> 1] = value >> 8; break; case RAM_FLAG_ODD: - gen->save_ram[address >> 1] = value; + gen->save_storage[address >> 1] = value; break; } } @@ -83,19 +83,19 @@ m68k_context * write_sram_area_b(uint32_t address, m68k_context * context, uint8 genesis_context * gen = context->system; if ((gen->bank_regs[0] & 0x3) == 1) { address &= gen->save_ram_mask; - switch(gen->save_flags) + switch(gen->save_type) { case RAM_FLAG_BOTH: - gen->save_ram[address] = value; + gen->save_storage[address] = value; break; case RAM_FLAG_EVEN: if (!(address & 1)) { - gen->save_ram[address >> 1] = value; + gen->save_storage[address >> 1] = value; } break; case RAM_FLAG_ODD: if (address & 1) { - gen->save_ram[address >> 1] = value; + gen->save_storage[address >> 1] = value; } break; } @@ -218,6 +218,13 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK; ram_start &= 0xFFFFFE; ram_end |= 1; + info->save_mask = ram_end - ram_start; + uint32_t size = info->save_mask + 1; + if (ram_flags != RAM_FLAG_BOTH) { + size /= 2; + } + info->save_size = size; + info->save_buffer = malloc(size); info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3); info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); @@ -232,18 +239,16 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk info->map[0].buffer = rom; info->map[1].start = ram_start; - info->map[1].mask = ram_end - ram_start; + info->map[1].mask = info->save_mask; info->map[1].end = ram_end + 1; info->map[1].flags = MMAP_READ | MMAP_WRITE; - uint32_t size = info->map[1].mask + 1; + if (ram_flags == RAM_FLAG_ODD) { info->map[1].flags |= MMAP_ONLY_ODD; - size /= 2; } else if (ram_flags == RAM_FLAG_EVEN) { info->map[1].flags |= MMAP_ONLY_EVEN; - size /= 2; } - info->map[1].buffer = malloc(size); + info->map[1].buffer = info->save_buffer; } else { //Assume the standard Sega mapper info->map[0].end = 0x200000; -- cgit v1.2.3 From 8af1d14863bb6ffad2c50b5275a848240c68c62e Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 7 Jul 2015 19:33:33 -0700 Subject: Add support for reading cartridge memory map from ROM database, though without EEPROM support for now --- romdb.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 98 insertions(+), 5 deletions(-) (limited to 'romdb.c') 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); } -- cgit v1.2.3 From da7c1f27d44cb1bb77c057ce9cca7041931619ae Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Fri, 10 Jul 2015 18:46:18 -0700 Subject: Initial work on I2C EEPROM implementation --- romdb.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 207 insertions(+), 3 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index bcd8c7b..ed845ab 100644 --- a/romdb.c +++ b/romdb.c @@ -16,6 +16,37 @@ #define RAM_END 0x1B8 #define REGION_START 0x1F0 +void eeprom_init(eeprom_state *state) +{ + state->slave_sda = 1; + state->host_sda = state->scl = 0; +} + +void set_host_sda(eeprom_state *state, uint8_t val) +{ + if (state->scl) { + if (val & ~state->host_sda) { + //stop condition + } else if (~val & state->host_sda) { + //start condition + } + } + state->host_sda = val; +} + +void set_scl(eeprom_state *state, uint8_t val) +{ + if (val & ~state->scl) { + //latch sda + } + state->scl = val; +} + +uint8_t get_sda(eeprom_state *state) +{ + return state->host_sda & state->slave_sda; +} + uint16_t read_sram_w(uint32_t address, m68k_context * context) { genesis_context * gen = context->system; @@ -136,6 +167,98 @@ m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_ } return context; } +eeprom_map *find_eeprom_map(uint32_t address, genesis_context *gen) +{ + for (int i = 0; i < gen->num_eeprom; i++) + { + if (address >= gen->eeprom_map[i].start && address <= gen->eeprom_map[i].end) { + return gen->eeprom_map + i; + } + } + return NULL; +} + +void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fprintf(stderr, "Could not find EEPROM map for address %X\n", address); + exit(1); + } + printf("EEPROM word write: %X - %X\n", address, value); + if (map->sda_write_mask) { + printf("sda: %d\n", (value & map->sda_write_mask) != 0); + set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); + } + if (map->scl_mask) { + printf("scl: %d\n", (value & map->scl_mask) != 0); + set_scl(&gen->eeprom, (value & map->sda_write_mask) != 0); + } + return context; +} + +void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fprintf(stderr, "Could not find EEPROM map for address %X\n", address); + exit(1); + } + + uint16_t expanded, mask; + if (address & 1) { + expanded = value; + mask = 0xFF; + } else { + expanded = value << 8; + mask = 0xFF00; + } + printf("EEPROM byte write: %X - %X (using mask %X and expanded val %X)\n", address, value, mask, expanded); + if (map->sda_write_mask & mask) { + printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); + set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); + } + if (map->scl_mask & mask) { + printf("scl: %d\n", (expanded & map->scl_mask) != 0); + set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); + } + return context; +} + +uint16_t read_eeprom_i2c_w(uint32_t address, void * context) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fprintf(stderr, "Could not find EEPROM map for address %X\n", address); + exit(1); + } + uint16_t ret = 0; + if (map->sda_read_bit < 16) { + ret = get_sda(&gen->eeprom) << map->sda_read_bit; + } + printf("EEPROM word read: %X - %X\n", address, ret); + return ret; +} + +uint8_t read_eeprom_i2c_b(uint32_t address, void * context) +{ + genesis_context *gen = ((m68k_context *)context)->system; + eeprom_map *map = find_eeprom_map(address, gen); + if (!map) { + fprintf(stderr, "Could not find EEPROM map for address %X\n", address); + exit(1); + } + uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8; + uint8_t ret = 0; + if (bit < 8) { + ret = get_sda(&gen->eeprom) << bit; + } + printf("EEPROM byte read: %X - %X\n", address, ret); + return ret; +} tern_node *load_rom_db() { @@ -316,8 +439,45 @@ typedef struct { tern_node *root; uint32_t rom_size; int index; + int num_els; } map_iter_state; +void eeprom_read_fun(char *key, tern_val val, void *data) +{ + int bit = atoi(key); + if (bit < 0 || bit > 15) { + fprintf(stderr, "bit %s is out of range", key); + return; + } + char *pin = val.ptrval; + if (strcmp(pin, "sda")) { + fprintf(stderr, "bit %s is connected to unrecognized read pin %s", key, pin); + return; + } + eeprom_map *map = data; + map->sda_read_bit = bit; +} + +void eeprom_write_fun(char *key, tern_val val, void *data) +{ + int bit = atoi(key); + if (bit < 0 || bit > 15) { + fprintf(stderr, "bit %s is out of range", key); + return; + } + char *pin = val.ptrval; + eeprom_map *map = data; + if (!strcmp(pin, "sda")) { + map->sda_write_mask = 1 << bit; + return; + } + if (!strcmp(pin, "scl")) { + map->scl_mask = 1 << bit; + return; + } + fprintf(stderr, "bit %s is connected to unrecognized write pin %s", key, pin); +} + void map_iter_fun(char *key, tern_val val, void *data) { map_iter_state *state = data; @@ -342,8 +502,50 @@ void map_iter_fun(char *key, tern_val val, void *data) map->flags = MMAP_READ; map->mask = calc_mask(state->rom_size, start, end); } else if (!strcmp(dtype, "EEPROM")) { - - + if (!state->info->save_size) { + char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval; + if (!size) { + fprintf(stderr, "ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); + exit(1); + } + state->info->save_size = atoi(size); + if (!state->info->save_size) { + fprintf(stderr, "EEPROM size %s is invalid\n", size); + exit(1); + } + char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval; + if (!etype) { + etype = "i2c"; + } + if (!strcmp(etype, "i2c")) { + state->info->save_type = SAVE_I2C; + } else { + fprintf(stderr, "EEPROM type %s is invalid\n", etype); + exit(1); + } + state->info->save_buffer = malloc(state->info->save_size); + state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els); + memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els); + } + eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom; + eep_map->start = start; + eep_map->end = end; + eep_map->sda_read_bit = 0xFF; + tern_node * bits_read = tern_find_ptr(node, "bits_read"); + if (bits_read) { + tern_foreach(bits_read, eeprom_read_fun, eep_map); + } + tern_node * bits_write = tern_find_ptr(node, "bits_write"); + if (bits_write) { + tern_foreach(bits_write, eeprom_write_fun, eep_map); + } + printf("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask); + state->info->num_eeprom++; + map->write_16 = write_eeprom_i2c_w; + map->write_8 = write_eeprom_i2c_b; + map->read_16 = read_eeprom_i2c_w; + map->read_8 = read_eeprom_i2c_b; + map->mask = 0xFFFFFF; } else if (!strcmp(dtype, "SRAM")) { if (!state->info->save_size) { char * size = tern_find_path(state->root, "SRAM\0size\0").ptrval; @@ -430,8 +632,10 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_ info.save_buffer = NULL; info.save_size = 0; info.map = malloc(sizeof(memmap_chunk) * info.map_chunks); + info.eeprom_map = NULL; + info.num_eeprom = 0; memset(info.map, 0, sizeof(memmap_chunk) * (info.map_chunks - base_chunks)); - map_iter_state state = {&info, rom, entry, rom_size, 0}; + map_iter_state state = {&info, rom, entry, rom_size, 0, info.map_chunks - base_chunks}; tern_foreach(map, map_iter_fun, &state); memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks); } else { -- cgit v1.2.3 From ec937eb637770838c92864d1d51393297a226d82 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Tue, 14 Jul 2015 18:28:05 -0700 Subject: Broken EEPROM support --- romdb.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 134 insertions(+), 7 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index ed845ab..072c1b1 100644 --- a/romdb.c +++ b/romdb.c @@ -16,19 +16,55 @@ #define RAM_END 0x1B8 #define REGION_START 0x1F0 -void eeprom_init(eeprom_state *state) +enum { + I2C_IDLE, + I2C_START, + I2C_DEVICE_ACK, + I2C_ADDRESS_HI, + I2C_ADDRESS_HI_ACK, + I2C_ADDRESS, + I2C_ADDRESS_ACK, + I2C_READ, + I2C_READ_ACK, + I2C_WRITE, + I2C_WRITE_ACK +}; + +char * i2c_states[] = { + "idle", + "start", + "device ack", + "address hi", + "address hi ack", + "address", + "address ack", + "read", + "read_ack", + "write", + "write_ack" +}; + +void eeprom_init(eeprom_state *state, uint8_t *buffer, uint32_t size) { state->slave_sda = 1; state->host_sda = state->scl = 0; + state->buffer = buffer; + state->size = size; + state->state = I2C_IDLE; } void set_host_sda(eeprom_state *state, uint8_t val) { if (state->scl) { if (val & ~state->host_sda) { - //stop condition + //low to high, stop condition + state->state = I2C_IDLE; + state->slave_sda = 1; } else if (~val & state->host_sda) { - //start condition + //high to low, start condition + state->state = I2C_START; + state->slave_sda = 1; + state->counter = 8; } } state->host_sda = val; @@ -37,7 +73,98 @@ void set_host_sda(eeprom_state *state, uint8_t val) void set_scl(eeprom_state *state, uint8_t val) { if (val & ~state->scl) { - //latch sda + //low to high transition + switch (state->state) + { + case I2C_START: + case I2C_ADDRESS_HI: + case I2C_ADDRESS: + case I2C_WRITE: + state->latch = state->host_sda << 7 | state->latch >> 1; + state->counter--; + if (!state->counter) { + switch (state->state & 0x7F) + { + case I2C_START: + state->state = I2C_DEVICE_ACK; + break; + case I2C_ADDRESS_HI: + state->address = state->latch << 8; + state->state = I2C_ADDRESS_HI_ACK; + break; + case I2C_ADDRESS: + state->address |= state->latch; + state->state = I2C_ADDRESS_ACK; + break; + case I2C_WRITE: + state->buffer[state->address] = state->latch; + state->state = I2C_WRITE_ACK; + state->address++; + //TODO: page mask + state->address &= state->size-1; + break; + } + } + break; + case I2C_DEVICE_ACK: + if (state->latch & 1) { + state->state = I2C_READ; + state->counter = 8; + state->latch = state->buffer[state->address]; + state->address++; + //TODO: page mask + state->address &= state->size-1; + } else { + if (state->size < 256) { + state->address = state->latch >> 1; + state->state = I2C_WRITE; + } else if (state->size < 8192) { + state->address = state->latch << 8; + state->state = I2C_ADDRESS; + } else { + state->state = I2C_ADDRESS_HI; + } + state->counter = 8; + } + break; + case I2C_ADDRESS_HI_ACK: + state->state = I2C_ADDRESS; + break; + case I2C_ADDRESS_ACK: + state->state = I2C_WRITE; + break; + case I2C_READ: + state->counter--; + if (!state->counter) { + state->state = I2C_READ_ACK; + } + break; + case I2C_READ_ACK: + state->state = I2C_READ; + break; + case I2C_WRITE_ACK: + state->state = I2C_WRITE; + break; + } + } else if (~val & state->scl) { + //high to low transition + switch (state->state & 0x7F) + { + case I2C_DEVICE_ACK: + case I2C_ADDRESS_HI_ACK: + case I2C_ADDRESS_ACK: + case I2C_READ_ACK: + case I2C_WRITE_ACK: + state->slave_sda = 0; + break; + case I2C_READ: + state->slave_sda = state->latch >> 7; + state->latch = state->latch << 1; + break; + default: + state->slave_sda = 1; + break; + } } state->scl = val; } @@ -192,8 +319,8 @@ void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); } if (map->scl_mask) { - printf("scl: %d\n", (value & map->scl_mask) != 0); - set_scl(&gen->eeprom, (value & map->sda_write_mask) != 0); + set_scl(&gen->eeprom, (value & map->scl_mask) != 0); + printf("scl: %d, state: %s, counter: %d\n", (value & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter); } return context; } @@ -221,7 +348,7 @@ void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); } if (map->scl_mask & mask) { - printf("scl: %d\n", (expanded & map->scl_mask) != 0); + printf("scl: %d, state: %s\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state]); set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); } return context; -- cgit v1.2.3 From 95c8581b8681a83c628409d8394c8fe95ccdfc33 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Fri, 17 Jul 2015 22:16:33 -0700 Subject: Less broken EEPROM support --- romdb.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 072c1b1..fc154c9 100644 --- a/romdb.c +++ b/romdb.c @@ -80,7 +80,7 @@ void set_scl(eeprom_state *state, uint8_t val) case I2C_ADDRESS_HI: case I2C_ADDRESS: case I2C_WRITE: - state->latch = state->host_sda << 7 | state->latch >> 1; + state->latch = state->host_sda | state->latch << 1; state->counter--; if (!state->counter) { switch (state->state & 0x7F) @@ -129,9 +129,11 @@ void set_scl(eeprom_state *state, uint8_t val) break; case I2C_ADDRESS_HI_ACK: state->state = I2C_ADDRESS; + state->counter = 8; break; case I2C_ADDRESS_ACK: state->state = I2C_WRITE; + state->counter = 8; break; case I2C_READ: state->counter--; @@ -141,9 +143,11 @@ void set_scl(eeprom_state *state, uint8_t val) break; case I2C_READ_ACK: state->state = I2C_READ; + state->counter = 8; break; case I2C_WRITE_ACK: state->state = I2C_WRITE; + state->counter = 8; break; } } else if (~val & state->scl) { @@ -314,14 +318,14 @@ void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) exit(1); } printf("EEPROM word write: %X - %X\n", address, value); + if (map->scl_mask) { + set_scl(&gen->eeprom, (value & map->scl_mask) != 0); + printf("scl: %d, state: %s, counter: %d, latch: %X\n", (value & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter, gen->eeprom.latch); + } if (map->sda_write_mask) { printf("sda: %d\n", (value & map->sda_write_mask) != 0); set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); } - if (map->scl_mask) { - set_scl(&gen->eeprom, (value & map->scl_mask) != 0); - printf("scl: %d, state: %s, counter: %d\n", (value & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter); - } return context; } @@ -343,14 +347,14 @@ void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) mask = 0xFF00; } printf("EEPROM byte write: %X - %X (using mask %X and expanded val %X)\n", address, value, mask, expanded); - if (map->sda_write_mask & mask) { - printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); - set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); - } if (map->scl_mask & mask) { printf("scl: %d, state: %s\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state]); set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); } + if (map->sda_write_mask & mask) { + printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); + set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); + } return context; } -- cgit v1.2.3 From df9080c523fd7a0f504b92e5f002645b484df9af Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 19 Jul 2015 20:51:09 -0700 Subject: Fix map for NFL Quarterback Club 96. Fix default EEPROM value. Initial work for supporing Sega mapper in ROM DB --- romdb.c | 178 +++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 114 insertions(+), 64 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index fc154c9..7748de0 100644 --- a/romdb.c +++ b/romdb.c @@ -609,6 +609,80 @@ void eeprom_write_fun(char *key, tern_val val, void *data) fprintf(stderr, "bit %s is connected to unrecognized write pin %s", key, pin); } +void process_sram_def(char *key, map_iter_state *state) +{ + 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); + memset(state->info->save_buffer, 0, 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; + } + } +} + +void process_eeprom_def(char * key, map_iter_state *state) +{ + if (!state->info->save_size) { + char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval; + if (!size) { + fprintf(stderr, "ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); + exit(1); + } + state->info->save_size = atoi(size); + if (!state->info->save_size) { + fprintf(stderr, "EEPROM size %s is invalid\n", size); + exit(1); + } + char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval; + if (!etype) { + etype = "i2c"; + } + if (!strcmp(etype, "i2c")) { + state->info->save_type = SAVE_I2C; + } else { + fprintf(stderr, "EEPROM type %s is invalid\n", etype); + exit(1); + } + state->info->save_buffer = malloc(state->info->save_size); + memset(state->info->save_buffer, 0xFF, state->info->save_size); + state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els); + memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els); + } +} + +void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_state *state) +{ + eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom; + eep_map->start = start; + eep_map->end = end; + eep_map->sda_read_bit = 0xFF; + tern_node * bits_read = tern_find_ptr(node, "bits_read"); + if (bits_read) { + tern_foreach(bits_read, eeprom_read_fun, eep_map); + } + tern_node * bits_write = tern_find_ptr(node, "bits_write"); + if (bits_write) { + tern_foreach(bits_write, eeprom_write_fun, eep_map); + } + printf("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask); + state->info->num_eeprom++; +} + void map_iter_fun(char *key, tern_val val, void *data) { map_iter_state *state = data; @@ -624,81 +698,25 @@ void map_iter_fun(char *key, tern_val val, void *data) exit(1); } char * dtype = tern_find_ptr_default(node, "device", "ROM"); - uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 0); + uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16); memmap_chunk *map = state->info->map + state->index; map->start = start; - map->end = end; + map->end = end + 1; if (!strcmp(dtype, "ROM")) { map->buffer = state->rom + offset; map->flags = MMAP_READ; - map->mask = calc_mask(state->rom_size, start, end); + map->mask = calc_mask(state->rom_size - offset, start, end); } else if (!strcmp(dtype, "EEPROM")) { - if (!state->info->save_size) { - char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval; - if (!size) { - fprintf(stderr, "ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); - exit(1); - } - state->info->save_size = atoi(size); - if (!state->info->save_size) { - fprintf(stderr, "EEPROM size %s is invalid\n", size); - exit(1); - } - char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval; - if (!etype) { - etype = "i2c"; - } - if (!strcmp(etype, "i2c")) { - state->info->save_type = SAVE_I2C; - } else { - fprintf(stderr, "EEPROM type %s is invalid\n", etype); - exit(1); - } - state->info->save_buffer = malloc(state->info->save_size); - state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els); - memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els); - } - eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom; - eep_map->start = start; - eep_map->end = end; - eep_map->sda_read_bit = 0xFF; - tern_node * bits_read = tern_find_ptr(node, "bits_read"); - if (bits_read) { - tern_foreach(bits_read, eeprom_read_fun, eep_map); - } - tern_node * bits_write = tern_find_ptr(node, "bits_write"); - if (bits_write) { - tern_foreach(bits_write, eeprom_write_fun, eep_map); - } - printf("EEPROM address %X: sda read: %X, sda write: %X, scl: %X\n", start, eep_map->sda_read_bit, eep_map->sda_write_mask, eep_map->scl_mask); - state->info->num_eeprom++; + process_eeprom_def(key, state); + add_eeprom_map(node, start, end, state); + map->write_16 = write_eeprom_i2c_w; map->write_8 = write_eeprom_i2c_b; map->read_16 = read_eeprom_i2c_w; map->read_8 = read_eeprom_i2c_b; map->mask = 0xFFFFFF; } 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; - } - } + process_sram_def(key, state); map->buffer = state->info->save_buffer + offset; map->flags = MMAP_READ | MMAP_WRITE; if (state->info->save_type == RAM_FLAG_ODD) { @@ -707,6 +725,37 @@ void map_iter_fun(char *key, tern_val val, void *data) map->flags |= MMAP_ONLY_EVEN; } map->mask = calc_mask(state->info->save_size, start, end); + } else if (!strcmp(dtype, "Sega mapper")) { + map->buffer = state->rom + offset; + //TODO: Calculate this + map->ptr_index = 2; + map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL; + map->mask = calc_mask(state->rom_size - offset, start, end); + char *save_device = tern_find_path(node, "save\0device\0").ptrval; + if (save_device && !strcmp(save_device, "SRAM")) { + process_sram_def(key, state); + map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL + map->read_8 = (read_8_fun)read_sram_b; + map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area + map->write_8 = (write_8_fun)write_sram_area_b; + } else if (save_device && !strcmp(save_device, "EEPROM")) { + process_eeprom_def(key, state); + add_eeprom_map(node, start & map->mask, end & map->mask, state); + map->write_16 = write_eeprom_i2c_w; + map->write_8 = write_eeprom_i2c_b; + map->read_16 = read_eeprom_i2c_w; + map->read_8 = read_eeprom_i2c_b; + } + state->info->map_chunks++; + state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); + state->index++; + memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk)); + map = state->info->map + state->index; + map->start = 0xA13000; + map->end = 0xA13100; + map->mask = 0xFF; + map->write_16 = (write_16_fun)write_bank_reg_w; + map->write_8 = (write_8_fun)write_bank_reg_b; } else { fprintf(stderr, "Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); exit(1); @@ -757,6 +806,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_ tern_node *map = tern_find_ptr(entry, "map"); if (map) { + info.save_type = SAVE_NONE; info.map_chunks = tern_count(map); if (info.map_chunks) { info.map_chunks += base_chunks; @@ -765,7 +815,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_ info.map = malloc(sizeof(memmap_chunk) * info.map_chunks); info.eeprom_map = NULL; info.num_eeprom = 0; - memset(info.map, 0, sizeof(memmap_chunk) * (info.map_chunks - base_chunks)); + memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); map_iter_state state = {&info, rom, entry, rom_size, 0, info.map_chunks - base_chunks}; tern_foreach(map, map_iter_fun, &state); memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks); -- cgit v1.2.3 From 5733306bcd4e653994b5830cf035e7487869aeb7 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sun, 19 Jul 2015 22:30:40 -0700 Subject: Populate save mask when SRAM is defined in ROM DB rather than cart header --- romdb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 7748de0..a422fe7 100644 --- a/romdb.c +++ b/romdb.c @@ -622,6 +622,7 @@ void process_sram_def(char *key, map_iter_state *state) fprintf(stderr, "SRAM size %s is invalid\n", size); exit(1); } + state->info->save_mask = nearest_pow2(state->info->save_size)-1; state->info->save_buffer = malloc(state->info->save_size); memset(state->info->save_buffer, 0, state->info->save_size); char *bus = tern_find_path(state->root, "SRAM\0bus\0").ptrval; -- cgit v1.2.3 From 9d475a3ccb5b2e1e206cf4c219ec5984cec3574f Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 20 Jul 2015 21:15:34 -0700 Subject: Full support for Sega mapper when it comes to data. Code in remapped sections may not work reliably. SSF2 now works. --- romdb.c | 84 +++++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 36 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index a422fe7..b79635e 100644 --- a/romdb.c +++ b/romdb.c @@ -273,10 +273,21 @@ m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16 gen->bank_regs[address] = value; if (!address) { if (value & 1) { - context->mem_pointers[2] = NULL; + for (int i = 0; i < 8; i++) + { + context->mem_pointers[gen->mapper_start_index + i] = NULL; + } } else { - context->mem_pointers[2] = cart + 0x200000/2; + //Used for games that only use the mapper for SRAM + context->mem_pointers[gen->mapper_start_index] = cart + 0x200000/2; + //For games that need more than 4MB + for (int i = 1; i < 8; i++) + { + context->mem_pointers[gen->mapper_start_index + i] = cart + 0x40000*gen->bank_regs[i]; + } } + } else { + context->mem_pointers[gen->mapper_start_index + address] = cart + 0x40000*value; } return context; } @@ -284,17 +295,7 @@ m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16 m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value) { if (address & 1) { - genesis_context * gen = context->system; - address &= 0xE; - address >>= 1; - gen->bank_regs[address] = value; - if (!address) { - if (value & 1) { - context->mem_pointers[2] = NULL; - } else { - context->mem_pointers[2] = cart + 0x200000/2; - } - } + write_bank_reg_w(address, context, value); } return context; } @@ -526,7 +527,7 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk info->map[1].end = 0x400000; info->map[1].mask = 0x1FFFFF; info->map[1].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL; - info->map[1].ptr_index = 2; + info->map[1].ptr_index = info->mapper_start_index = 0; info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL info->map[1].read_8 = (read_8_fun)read_sram_b; info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area @@ -571,6 +572,7 @@ typedef struct { uint32_t rom_size; int index; int num_els; + uint16_t ptr_index; } map_iter_state; void eeprom_read_fun(char *key, tern_val val, void *data) @@ -727,31 +729,41 @@ void map_iter_fun(char *key, tern_val val, void *data) } map->mask = calc_mask(state->info->save_size, start, end); } else if (!strcmp(dtype, "Sega mapper")) { - map->buffer = state->rom + offset; - //TODO: Calculate this - map->ptr_index = 2; - map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL; - map->mask = calc_mask(state->rom_size - offset, start, end); + state->info->mapper_start_index = state->ptr_index++; + state->info->map_chunks+=7; + state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); + memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7); + map = state->info->map + state->index; char *save_device = tern_find_path(node, "save\0device\0").ptrval; - if (save_device && !strcmp(save_device, "SRAM")) { - process_sram_def(key, state); - map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL - map->read_8 = (read_8_fun)read_sram_b; - map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area - map->write_8 = (write_8_fun)write_sram_area_b; - } else if (save_device && !strcmp(save_device, "EEPROM")) { + if (save_device && !strcmp(save_device, "EEPROM")) { process_eeprom_def(key, state); add_eeprom_map(node, start & map->mask, end & map->mask, state); - map->write_16 = write_eeprom_i2c_w; - map->write_8 = write_eeprom_i2c_b; - map->read_16 = read_eeprom_i2c_w; - map->read_8 = read_eeprom_i2c_b; } - state->info->map_chunks++; - state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks); - state->index++; - memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk)); - map = state->info->map + state->index; + for (int i = 0; i < 7; i++, state->index++, map++) + { + map->start = start + i * 0x80000; + map->end = start + (i + 1) * 0x80000; + map->mask = 0x7FFFF; + map->buffer = state->rom + offset + i * 0x80000; + map->ptr_index = state->ptr_index++; + if (i < 3 || !save_device) { + map->flags = MMAP_READ | MMAP_PTR_IDX; + } else { + map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL; + if (!strcmp(save_device, "SRAM")) { + process_sram_def(key, state); + map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL + map->read_8 = (read_8_fun)read_sram_b; + map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area + map->write_8 = (write_8_fun)write_sram_area_b; + } else if (!strcmp(save_device, "EEPROM")) { + map->write_16 = write_eeprom_i2c_w; + map->write_8 = write_eeprom_i2c_b; + map->read_16 = read_eeprom_i2c_w; + map->read_8 = read_eeprom_i2c_b; + } + } + } map->start = 0xA13000; map->end = 0xA13100; map->mask = 0xFF; @@ -817,7 +829,7 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, memmap_ info.eeprom_map = NULL; info.num_eeprom = 0; memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks); - map_iter_state state = {&info, rom, entry, rom_size, 0, info.map_chunks - base_chunks}; + map_iter_state state = {&info, rom, entry, rom_size, 0, info.map_chunks - base_chunks, 0}; tern_foreach(map, map_iter_fun, &state); memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks); } else { -- cgit v1.2.3 From 3a192413d7a2251f3c69504d13ae3611e6c58404 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 20 Jul 2015 21:43:17 -0700 Subject: Support large flat-mapped ROMs like Bad Apple or that Mortal Kombat hack --- romdb.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index b79635e..2cab3c2 100644 --- a/romdb.c +++ b/romdb.c @@ -478,20 +478,25 @@ uint32_t calc_mask(uint32_t src_size, uint32_t start, uint32_t end) void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks) { + uint32_t rom_end = get_u32be(rom + ROM_END) + 1; + if (size > rom_end) { + rom_end = size; + } else if (rom_end > nearest_pow2(size)) { + rom_end = nearest_pow2(size); + } if (rom[RAM_ID] == 'R' && rom[RAM_ID+1] == 'A') { - uint32_t rom_end = get_u32be(rom + ROM_END) + 1; uint32_t ram_start = get_u32be(rom + RAM_START); uint32_t ram_end = get_u32be(rom + RAM_END); uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK; ram_start &= 0xFFFFFE; ram_end |= 1; info->save_mask = ram_end - ram_start; - uint32_t size = info->save_mask + 1; + uint32_t save_size = info->save_mask + 1; if (ram_flags != RAM_FLAG_BOTH) { - size /= 2; + save_size /= 2; } - info->save_size = size; - info->save_buffer = malloc(size); + info->save_size = save_size; + info->save_buffer = malloc(save_size); info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3); info->map = malloc(sizeof(memmap_chunk) * info->map_chunks); @@ -499,7 +504,7 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks); if (ram_start >= rom_end) { - info->map[0].end = rom_end; + info->map[0].end = rom_end > 0x400000 ? rom_end : 0x400000; //TODO: ROM mirroring info->map[0].mask = 0xFFFFFF; info->map[0].flags = MMAP_READ; @@ -548,7 +553,7 @@ void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk memset(info->map, 0, sizeof(memmap_chunk)); memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks); - info->map[0].end = 0x400000; + info->map[0].end =rom_end > 0x400000 ? rom_end : 0x400000; info->map[0].mask = 0xFFFFFF; info->map[0].flags = MMAP_READ; info->map[0].buffer = rom; -- cgit v1.2.3 From dcff6b6b16c292943e905ed7986664ff0f4a05be Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 20 Jul 2015 22:22:49 -0700 Subject: EEPROM writes now seem to work for NFL Quarterback Club 96 --- romdb.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 2cab3c2..ff4e65a 100644 --- a/romdb.c +++ b/romdb.c @@ -99,9 +99,6 @@ void set_scl(eeprom_state *state, uint8_t val) case I2C_WRITE: state->buffer[state->address] = state->latch; state->state = I2C_WRITE_ACK; - state->address++; - //TODO: page mask - state->address &= state->size-1; break; } } @@ -111,15 +108,12 @@ void set_scl(eeprom_state *state, uint8_t val) state->state = I2C_READ; state->counter = 8; state->latch = state->buffer[state->address]; - state->address++; - //TODO: page mask - state->address &= state->size-1; } else { if (state->size < 256) { state->address = state->latch >> 1; state->state = I2C_WRITE; - } else if (state->size < 8192) { - state->address = state->latch << 8; + } else if (state->size < 4096) { + state->address = (state->latch & 0xE) << 7; state->state = I2C_ADDRESS; } else { state->state = I2C_ADDRESS_HI; @@ -133,6 +127,8 @@ void set_scl(eeprom_state *state, uint8_t val) break; case I2C_ADDRESS_ACK: state->state = I2C_WRITE; + state->address &= state->size-1; + printf("EEPROM address is %X\n", state->address); state->counter = 8; break; case I2C_READ: @@ -144,10 +140,16 @@ void set_scl(eeprom_state *state, uint8_t val) case I2C_READ_ACK: state->state = I2C_READ; state->counter = 8; + state->address++; + //TODO: page mask + state->address &= state->size-1; break; case I2C_WRITE_ACK: state->state = I2C_WRITE; state->counter = 8; + state->address++; + //TODO: page mask + state->address &= state->size-1; break; } } else if (~val & state->scl) { @@ -349,8 +351,8 @@ void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) } printf("EEPROM byte write: %X - %X (using mask %X and expanded val %X)\n", address, value, mask, expanded); if (map->scl_mask & mask) { - printf("scl: %d, state: %s\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state]); set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); + printf("scl: %d, state: %s, counter: %d, latch: %X\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter, gen->eeprom.latch); } if (map->sda_write_mask & mask) { printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); -- cgit v1.2.3 From 6f6468a4e6cb2e4c487d9ef3f59f87390e0f3015 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 20 Jul 2015 23:11:42 -0700 Subject: EEPROM reads now work for NFL Quarterback Club 96 --- romdb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index ff4e65a..6dd70a7 100644 --- a/romdb.c +++ b/romdb.c @@ -143,6 +143,7 @@ void set_scl(eeprom_state *state, uint8_t val) state->address++; //TODO: page mask state->address &= state->size-1; + state->latch = state->buffer[state->address]; break; case I2C_WRITE_ACK: state->state = I2C_WRITE; -- cgit v1.2.3 From 25488e46291a19514f81194f8fd1cef10e2a7549 Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Mon, 20 Jul 2015 23:18:29 -0700 Subject: Remove debug printf from EEPROM code --- romdb.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 6dd70a7..925fcd1 100644 --- a/romdb.c +++ b/romdb.c @@ -128,7 +128,6 @@ void set_scl(eeprom_state *state, uint8_t val) case I2C_ADDRESS_ACK: state->state = I2C_WRITE; state->address &= state->size-1; - printf("EEPROM address is %X\n", state->address); state->counter = 8; break; case I2C_READ: @@ -321,13 +320,10 @@ void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) fprintf(stderr, "Could not find EEPROM map for address %X\n", address); exit(1); } - printf("EEPROM word write: %X - %X\n", address, value); if (map->scl_mask) { set_scl(&gen->eeprom, (value & map->scl_mask) != 0); - printf("scl: %d, state: %s, counter: %d, latch: %X\n", (value & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter, gen->eeprom.latch); } if (map->sda_write_mask) { - printf("sda: %d\n", (value & map->sda_write_mask) != 0); set_host_sda(&gen->eeprom, (value & map->sda_write_mask) != 0); } return context; @@ -350,13 +346,10 @@ void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) expanded = value << 8; mask = 0xFF00; } - printf("EEPROM byte write: %X - %X (using mask %X and expanded val %X)\n", address, value, mask, expanded); if (map->scl_mask & mask) { set_scl(&gen->eeprom, (expanded & map->scl_mask) != 0); - printf("scl: %d, state: %s, counter: %d, latch: %X\n", (expanded & map->scl_mask) != 0, i2c_states[gen->eeprom.state], gen->eeprom.counter, gen->eeprom.latch); } if (map->sda_write_mask & mask) { - printf("sda: %d\n", (expanded & map->sda_write_mask) != 0); set_host_sda(&gen->eeprom, (expanded & map->sda_write_mask) != 0); } return context; @@ -374,7 +367,6 @@ uint16_t read_eeprom_i2c_w(uint32_t address, void * context) if (map->sda_read_bit < 16) { ret = get_sda(&gen->eeprom) << map->sda_read_bit; } - printf("EEPROM word read: %X - %X\n", address, ret); return ret; } @@ -391,7 +383,6 @@ uint8_t read_eeprom_i2c_b(uint32_t address, void * context) if (bit < 8) { ret = get_sda(&gen->eeprom) << bit; } - printf("EEPROM byte read: %X - %X\n", address, ret); return ret; } -- cgit v1.2.3 From 80ff833dd8ad011b579bff26ac654819e6735bce Mon Sep 17 00:00:00 2001 From: Michael Pavone Date: Sat, 25 Jul 2015 18:22:07 -0700 Subject: Use a new fatal_error function instead of calling fprintf and exit for fatal errors. This new function more gracefully handles the case in which BlastEm was not started from a terminal or disconnected from ther terminal (Windows). --- romdb.c | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) (limited to 'romdb.c') diff --git a/romdb.c b/romdb.c index 925fcd1..8ccd76b 100644 --- a/romdb.c +++ b/romdb.c @@ -317,8 +317,7 @@ void * write_eeprom_i2c_w(uint32_t address, void * context, uint16_t value) genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } if (map->scl_mask) { set_scl(&gen->eeprom, (value & map->scl_mask) != 0); @@ -334,8 +333,7 @@ void * write_eeprom_i2c_b(uint32_t address, void * context, uint8_t value) genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint16_t expanded, mask; @@ -360,8 +358,7 @@ uint16_t read_eeprom_i2c_w(uint32_t address, void * context) genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint16_t ret = 0; if (map->sda_read_bit < 16) { @@ -375,8 +372,7 @@ uint8_t read_eeprom_i2c_b(uint32_t address, void * context) genesis_context *gen = ((m68k_context *)context)->system; eeprom_map *map = find_eeprom_map(address, gen); if (!map) { - fprintf(stderr, "Could not find EEPROM map for address %X\n", address); - exit(1); + fatal_error("Could not find EEPROM map for address %X\n", address); } uint8_t bit = address & 1 ? map->sda_read_bit : map->sda_read_bit - 8; uint8_t ret = 0; @@ -390,14 +386,13 @@ tern_node *load_rom_db() { char *exe_dir = get_exe_dir(); if (!exe_dir) { - fputs("Failed to find executable path\n", stderr); - exit(1); + fatal_error("Failed to find executable path\n"); } char *path = alloc_concat(exe_dir, "/rom.db"); tern_node *db = parse_config_file(path); free(path); if (!db) { - fputs("Failed to load ROM DB\n", stderr); + fatal_error("Failed to load ROM DB\n"); } return db; } @@ -615,13 +610,11 @@ void process_sram_def(char *key, map_iter_state *state) 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); + fatal_error("ROM DB map entry %d with address %s has device type SRAM, but the SRAM size is not defined\n", state->index, key); } state->info->save_size = atoi(size); if (!state->info->save_size) { - fprintf(stderr, "SRAM size %s is invalid\n", size); - exit(1); + fatal_error("SRAM size %s is invalid\n", size); } state->info->save_mask = nearest_pow2(state->info->save_size)-1; state->info->save_buffer = malloc(state->info->save_size); @@ -642,13 +635,11 @@ void process_eeprom_def(char * key, map_iter_state *state) if (!state->info->save_size) { char * size = tern_find_path(state->root, "EEPROM\0size\0").ptrval; if (!size) { - fprintf(stderr, "ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); - exit(1); + fatal_error("ROM DB map entry %d with address %s has device type EEPROM, but the EEPROM size is not defined\n", state->index, key); } state->info->save_size = atoi(size); if (!state->info->save_size) { - fprintf(stderr, "EEPROM size %s is invalid\n", size); - exit(1); + fatal_error("EEPROM size %s is invalid\n", size); } char *etype = tern_find_path(state->root, "EEPROM\0type\0").ptrval; if (!etype) { @@ -657,8 +648,7 @@ void process_eeprom_def(char * key, map_iter_state *state) if (!strcmp(etype, "i2c")) { state->info->save_type = SAVE_I2C; } else { - fprintf(stderr, "EEPROM type %s is invalid\n", etype); - exit(1); + fatal_error("EEPROM type %s is invalid\n", etype); } state->info->save_buffer = malloc(state->info->save_size); memset(state->info->save_buffer, 0xFF, state->info->save_size); @@ -690,14 +680,12 @@ 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); + fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key); } 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); + fatal_error("'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key); } char * dtype = tern_find_ptr_default(node, "device", "ROM"); uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16); @@ -769,8 +757,7 @@ void map_iter_fun(char *key, tern_val val, void *data) map->write_16 = (write_16_fun)write_bank_reg_w; map->write_8 = (write_8_fun)write_bank_reg_b; } else { - fprintf(stderr, "Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); - exit(1); + fatal_error("Invalid device type for ROM DB map entry %d with address %s\n", state->index, key); } state->index++; } -- cgit v1.2.3