main romdb.c
  1#include <stdlib.h>
  2#include <string.h>
  3#include "config.h"
  4#include "romdb.h"
  5#include "util.h"
  6#include "hash.h"
  7#include "genesis.h"
  8#include "menu.h"
  9#include "xband.h"
 10#include "realtec.h"
 11#include "nor.h"
 12#include "sega_mapper.h"
 13#include "multi_game.h"
 14#include "megawifi.h"
 15#include "jcart.h"
 16#include "blastem.h"
 17
 18#define DOM_TITLE_START 0x120
 19#define DOM_TITLE_END 0x150
 20#define TITLE_START DOM_TITLE_END
 21#define TITLE_END (TITLE_START+48)
 22#define ROM_END   0x1A4
 23#define RAM_ID    0x1B0
 24#define RAM_FLAGS 0x1B2
 25#define RAM_START 0x1B4
 26#define RAM_END   0x1B8
 27#define REGION_START 0x1F0
 28
 29char const *save_type_name(uint8_t save_type)
 30{
 31	if (save_type == SAVE_I2C) {
 32		return "EEPROM";
 33	} else if(save_type == SAVE_NOR) {
 34		return "NOR Flash";
 35	}
 36	return "SRAM";
 37}
 38
 39tern_node *load_rom_db()
 40{
 41	tern_node *db = parse_bundled_config("rom.db");
 42	if (!db) {
 43		fatal_error("Failed to load ROM DB\n");
 44	}
 45	return db;
 46}
 47
 48void free_rom_info(rom_info *info)
 49{
 50	free(info->name);
 51	if (info->save_type != SAVE_NONE) {
 52		free(info->save_buffer);
 53		if (info->save_type == SAVE_I2C) {
 54			free(info->eeprom_map);
 55		} else if (info->save_type == SAVE_NOR) {
 56			free(info->nor);
 57		}
 58	}
 59	free(info->map);
 60	free(info->port1_override);
 61	free(info->port2_override);
 62	free(info->ext_override);
 63	free(info->mouse_mode);
 64}
 65
 66void cart_serialize(system_header *sys, serialize_buffer *buf)
 67{
 68	if (sys->type != SYSTEM_GENESIS) {
 69		return;
 70	}
 71	genesis_context *gen = (genesis_context *)sys;
 72	if (gen->mapper_type == MAPPER_NONE) {
 73		return;
 74	}
 75	start_section(buf, SECTION_MAPPER);
 76	save_int8(buf, gen->mapper_type);
 77	switch(gen->mapper_type)
 78	{
 79	case MAPPER_SEGA:
 80		sega_mapper_serialize(gen, buf);
 81		break;
 82	case MAPPER_REALTEC:
 83		realtec_serialize(gen, buf);
 84		break;
 85	case MAPPER_XBAND:
 86		xband_serialize(gen, buf);
 87		break;
 88	case MAPPER_MULTI_GAME:
 89		multi_game_serialize(gen, buf);
 90		break;
 91	}
 92	end_section(buf);
 93}
 94
 95void cart_deserialize(deserialize_buffer *buf, void *vcontext)
 96{
 97	genesis_context *gen = vcontext;
 98	uint8_t mapper_type = load_int8(buf);
 99	if (mapper_type != gen->mapper_type) {
100		warning("Mapper type mismatch, skipping load of mapper state");
101		return;
102	}
103	switch(gen->mapper_type)
104	{
105	case MAPPER_SEGA:
106		sega_mapper_deserialize(buf, gen);
107		break;
108	case MAPPER_REALTEC:
109		realtec_deserialize(buf, gen);
110		break;
111	case MAPPER_XBAND:
112		xband_deserialize(buf, gen);
113		break;
114	case MAPPER_MULTI_GAME:
115		multi_game_deserialize(buf, gen);
116		break;
117	}
118}
119
120char *get_header_name(uint8_t *rom)
121{
122	//TODO: Should probably prefer the title field that corresponds to the user's region preference
123	uint8_t *last = rom + TITLE_END - 1;
124	uint8_t *src = rom + TITLE_START;
125	
126	for (;;)
127	{
128		while (last > src && (*last <=  0x20 || *last >= 0x80))
129		{
130			last--;
131		}
132		if (last == src) {
133			if (src == rom + TITLE_START) {
134				src = rom + DOM_TITLE_START;
135				last = rom + DOM_TITLE_END - 1;
136			} else {
137				return strdup("UNKNOWN");
138			}
139		} else {
140			last++;
141			char *ret = malloc(last - src + 1);
142			uint8_t *dst;
143			uint8_t last_was_space = 1;
144			for (dst = ret; src < last; src++)
145			{
146				if (*src >= 0x20 && *src < 0x80) {
147					if (*src == ' ') {
148						if (last_was_space) {
149							continue;
150						}
151						last_was_space = 1;
152					} else {
153						last_was_space = 0;
154					}
155					*(dst++) = *src;
156				}
157			}
158			*dst = 0;
159			return ret;
160		}
161	}
162}
163
164char *region_chars = "JUEW";
165uint8_t region_bits[] = {REGION_J, REGION_U, REGION_E, REGION_J|REGION_U|REGION_E};
166
167uint8_t translate_region_char(uint8_t c)
168{	
169	for (int i = 0; i < sizeof(region_bits); i++)
170	{
171		if (c == region_chars[i]) {
172			return region_bits[i];
173		}
174	}
175	uint8_t bin_region = 0;
176	if (c >= '0' && c <= '9') {
177		bin_region = c - '0';
178	} else if (c >= 'A' && c <= 'F') {
179		bin_region = c - 'A' + 0xA;
180	} else if (c >= 'a' && c <= 'f') {
181		bin_region = c - 'a' + 0xA;
182	}
183	uint8_t ret = 0;
184	if (bin_region & 8) {
185		ret |= REGION_E;
186	}
187	if (bin_region & 4) {
188		ret |= REGION_U;
189	}
190	if (bin_region & 1) {
191		ret |= REGION_J;
192	}
193	return ret;
194}
195
196uint8_t get_header_regions(uint8_t *rom)
197{
198	uint8_t regions = 0;
199	for (int i = 0; i < 3; i++)
200	{
201		regions |= translate_region_char(rom[REGION_START + i]);
202	}
203	return regions;
204}
205
206uint32_t get_u32be(uint8_t *data)
207{
208	return *data << 24 | data[1] << 16 | data[2] << 8 | data[3];
209}
210
211uint32_t calc_mask(uint32_t src_size, uint32_t start, uint32_t end)
212{
213	uint32_t map_size = end-start+1;
214	if (src_size < map_size) {
215		return nearest_pow2(src_size)-1;
216	} else if (!start) {
217		return 0xFFFFFF;
218	} else {
219		return nearest_pow2(map_size)-1;
220	}
221}
222
223uint8_t has_ram_header(uint8_t *rom, uint32_t rom_size)
224{
225	return rom_size >= (RAM_END + 4) && rom[RAM_ID] == 'R' && rom[RAM_ID + 1] == 'A'; 
226}
227
228uint32_t read_ram_header(rom_info *info, uint8_t *rom)
229{
230	uint32_t ram_start = get_u32be(rom + RAM_START);
231	uint32_t ram_end = get_u32be(rom + RAM_END);
232	uint32_t ram_flags = info->save_type = rom[RAM_FLAGS] & RAM_FLAG_MASK;
233	ram_start &= 0xFFFFFE;
234	ram_end |= 1;
235	if (ram_start >= 0x800000) {
236		info->save_buffer = NULL;
237		return ram_start;
238	}
239	info->save_mask = ram_end - ram_start;
240	uint32_t save_size = info->save_mask + 1;
241	if (ram_flags != RAM_FLAG_BOTH) {
242		save_size /= 2;
243	}
244	info->save_size = save_size;
245	info->save_buffer = malloc(save_size);
246	return ram_start;
247}
248
249void add_memmap_header(rom_info *info, uint8_t *rom, uint32_t size, memmap_chunk const *base_map, int base_chunks)
250{
251	uint32_t rom_end = get_u32be(rom + ROM_END) + 1;
252	if (size > rom_end) {
253		rom_end = size;
254	} else if (rom_end > nearest_pow2(size)) {
255		rom_end = nearest_pow2(size);
256	}
257	if (size >= 0x80000 && !memcmp("SEGA SSF", rom + 0x100, 8)) {
258		info->mapper_start_index = 0;
259		info->mapper_type = MAPPER_SEGA;
260		info->map_chunks = base_chunks + 9;
261		info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
262		memset(info->map, 0, sizeof(memmap_chunk)*9);
263		memcpy(info->map+9, base_map, sizeof(memmap_chunk) * base_chunks);
264		
265		info->map[0].start = 0;
266		info->map[0].end = 0x80000;
267		info->map[0].mask = 0xFFFFFF;
268		info->map[0].flags = MMAP_READ;
269		info->map[0].buffer = rom;
270		
271		if (has_ram_header(rom, size)){
272			read_ram_header(info, rom);
273		}
274		
275		for (int i = 1; i < 8; i++)
276		{
277			info->map[i].start = i * 0x80000;
278			info->map[i].end = (i + 1) * 0x80000;
279			info->map[i].mask = 0x7FFFF;
280			info->map[i].buffer = (i + 1) * 0x80000 <= size ? rom + i * 0x80000 : rom;
281			info->map[i].ptr_index = i;
282			info->map[i].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
283			
284			info->map[i].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[i] == NULL
285			info->map[i].read_8 = (read_8_fun)read_sram_b;
286			info->map[i].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
287			info->map[i].write_8 = (write_8_fun)write_sram_area_b;
288			
289		}
290		info->map[8].start = 0xA13000;
291		info->map[8].end = 0xA13100;
292		info->map[8].mask = 0xFF;
293		info->map[8].write_16 = (write_16_fun)write_bank_reg_w;
294		info->map[8].write_8 = (write_8_fun)write_bank_reg_b;
295		return;
296	} else if(!memcmp("SEGA MEGAWIFI", rom + 0x100, strlen("SEGA MEGAWIFI"))) {
297		info->mapper_type = MAPPER_NONE;
298		info->map_chunks = base_chunks + 2;
299		info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
300		memset(info->map, 0, sizeof(memmap_chunk)*2);
301		memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks);
302		info->save_size = 0x400000;
303		info->save_bus = RAM_FLAG_BOTH;
304		info->save_type = SAVE_NOR;
305		info->map[0].start = 0;
306		info->map[0].end = 0x400000;
307		info->map[0].mask = 0xFFFFFF;
308		info->map[0].write_16 = nor_flash_write_w;
309		info->map[0].write_8 = nor_flash_write_b;
310		info->map[0].read_16 = nor_flash_read_w;
311		info->map[0].read_8 = nor_flash_read_b;
312		info->map[0].flags = MMAP_READ_CODE | MMAP_CODE;
313		info->map[0].buffer = info->save_buffer = malloc(info->save_size);
314		uint32_t init_size = size < info->save_size ? size : info->save_size;
315		memcpy(info->save_buffer, rom, init_size);
316		byteswap_rom(info->save_size, (uint16_t *)info->save_buffer);
317		info->nor = calloc(1, sizeof(nor_state));
318		nor_flash_init(info->nor, info->save_buffer, info->save_size, 128, 0xDA45, RAM_FLAG_BOTH);
319		info->nor->cmd_address1 = 0xAAB;
320		info->nor->cmd_address2 = 0x555;
321		info->map[1].start = 0xA130C0;
322		info->map[1].end = 0xA130D0;
323		info->map[1].mask = 0xFFFFFF;
324		if (!strcmp(
325			"on", 
326			tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
327		) {
328			info->map[1].write_16 = megawifi_write_w;
329			info->map[1].write_8 = megawifi_write_b;
330			info->map[1].read_16 = megawifi_read_w;
331			info->map[1].read_8 = megawifi_read_b;
332		} else {
333			warning("ROM uses MegaWiFi, but it is disabled\n");
334		}
335		return;
336	} else if (has_ram_header(rom, size)) {
337		uint32_t ram_start = read_ram_header(info, rom);
338
339		if (info->save_buffer) {
340			info->map_chunks = base_chunks + (ram_start >= rom_end ? 2 : 3);
341			info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
342			memset(info->map, 0, sizeof(memmap_chunk)*2);
343			memcpy(info->map+2, base_map, sizeof(memmap_chunk) * base_chunks);
344
345			if (ram_start >= rom_end) {
346				info->map[0].end = rom_end < 0x400000 ? nearest_pow2(rom_end) - 1 : 0xFFFFFF;
347				if (info->map[0].end > ram_start) {
348					info->map[0].end = ram_start;
349				}
350				//TODO: ROM mirroring
351				info->map[0].mask = 0xFFFFFF;
352				info->map[0].flags = MMAP_READ;
353				info->map[0].buffer = rom;
354
355				info->map[1].start = ram_start;
356				info->map[1].mask = info->save_mask;
357				info->map[1].end = ram_start + info->save_mask + 1;
358				info->map[1].flags = MMAP_READ | MMAP_WRITE;
359
360				if (info->save_type == RAM_FLAG_ODD) {
361					info->map[1].flags |= MMAP_ONLY_ODD;
362				} else if (info->save_type == RAM_FLAG_EVEN) {
363					info->map[1].flags |= MMAP_ONLY_EVEN;
364				}
365				info->map[1].buffer = info->save_buffer;
366			} else {
367				//Assume the standard Sega mapper
368				info->mapper_type = MAPPER_SEGA;
369				info->map[0].end = 0x200000;
370				info->map[0].mask = 0xFFFFFF;
371				info->map[0].flags = MMAP_READ;
372				info->map[0].buffer = rom;
373
374				info->map[1].start = 0x200000;
375				info->map[1].end = 0x400000;
376				info->map[1].mask = 0x1FFFFF;
377				info->map[1].flags = MMAP_READ | MMAP_PTR_IDX | MMAP_FUNC_NULL;
378				info->map[1].ptr_index = info->mapper_start_index = 0;
379				info->map[1].read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
380				info->map[1].read_8 = (read_8_fun)read_sram_b;
381				info->map[1].write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
382				info->map[1].write_8 = (write_8_fun)write_sram_area_b;
383				info->map[1].buffer = rom + 0x200000;
384
385				memmap_chunk *last = info->map + info->map_chunks - 1;
386				memset(last, 0, sizeof(memmap_chunk));
387				last->start = 0xA13000;
388				last->end = 0xA13100;
389				last->mask = 0xFF;
390				last->write_16 = (write_16_fun)write_bank_reg_w;
391				last->write_8 = (write_8_fun)write_bank_reg_b;
392			}
393			return;
394		}
395	}
396	
397	info->map_chunks = base_chunks + 1;
398	info->map = malloc(sizeof(memmap_chunk) * info->map_chunks);
399	memset(info->map, 0, sizeof(memmap_chunk));
400	memcpy(info->map+1, base_map, sizeof(memmap_chunk) * base_chunks);
401
402	info->map[0].end = rom_end > 0x400000 ? rom_end : 0x400000;
403	info->map[0].mask = rom_end < 0x400000 ? nearest_pow2(rom_end) - 1 : 0xFFFFFF;
404	info->map[0].flags = MMAP_READ;
405	info->map[0].buffer = rom;
406	info->save_type = SAVE_NONE;
407}
408
409rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk const *base_map, uint32_t base_chunks)
410{
411	rom_info info;
412	info.mapper_type = MAPPER_NONE;
413	info.name = get_header_name(rom);
414	info.regions = get_header_regions(rom);
415	info.is_save_lock_on = 0;
416	info.rom = rom;
417	info.rom_size = rom_size;
418	add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
419	info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
420	return info;
421}
422
423typedef struct {
424	rom_info     *info;
425	uint8_t      *rom;
426	uint8_t      *lock_on;
427	tern_node    *root;
428	tern_node    *rom_db;
429	uint32_t     rom_size;
430	uint32_t     lock_on_size;
431	int          index;
432	int          num_els;
433	uint16_t     ptr_index;
434} map_iter_state;
435
436void eeprom_read_fun(char *key, tern_val val, uint8_t valtype, void *data)
437{
438	int bit = atoi(key);
439	if (bit < 0 || bit > 15) {
440		fprintf(stderr, "bit %s is out of range", key);
441		return;
442	}
443	if (valtype != TVAL_PTR) {
444		fprintf(stderr, "bit %s has a non-scalar value", key);
445		return;
446	}
447	char *pin = val.ptrval;
448	if (strcmp(pin, "sda")) {
449		fprintf(stderr, "bit %s is connected to unrecognized read pin %s", key, pin);
450		return;
451	}
452	eeprom_map *map = data;
453	map->sda_read_bit = bit;
454}
455
456void eeprom_write_fun(char *key, tern_val val, uint8_t valtype, void *data)
457{
458	int bit = atoi(key);
459	if (bit < 0 || bit > 15) {
460		fprintf(stderr, "bit %s is out of range", key);
461		return;
462	}
463	if (valtype != TVAL_PTR) {
464		fprintf(stderr, "bit %s has a non-scalar value", key);
465		return;
466	}
467	char *pin = val.ptrval;
468	eeprom_map *map = data;
469	if (!strcmp(pin, "sda")) {
470		map->sda_write_mask = 1 << bit;
471		return;
472	}
473	if (!strcmp(pin, "scl")) {
474		map->scl_mask = 1 << bit;
475		return;
476	}
477	fprintf(stderr, "bit %s is connected to unrecognized write pin %s", key, pin);
478}
479
480void process_sram_def(char *key, map_iter_state *state)
481{
482	if (!state->info->save_size) {
483		char * size = tern_find_path(state->root, "SRAM\0size\0", TVAL_PTR).ptrval;
484		if (!size) {
485			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);
486		}
487		state->info->save_size = atoi(size);
488		if (!state->info->save_size) {
489			fatal_error("SRAM size %s is invalid\n", size);
490		}
491		state->info->save_mask = nearest_pow2(state->info->save_size)-1;
492		state->info->save_buffer = malloc(state->info->save_size);
493		memset(state->info->save_buffer, 0, state->info->save_size);
494		char *bus = tern_find_path(state->root, "SRAM\0bus\0", TVAL_PTR).ptrval;
495		if (!strcmp(bus, "odd")) {
496			state->info->save_type = RAM_FLAG_ODD;
497		} else if(!strcmp(bus, "even")) {
498			state->info->save_type = RAM_FLAG_EVEN;
499		} else {
500			state->info->save_type = RAM_FLAG_BOTH;
501		}
502	}
503}
504
505void process_eeprom_def(char * key, map_iter_state *state)
506{
507	if (!state->info->save_size) {
508		char * size = tern_find_path(state->root, "EEPROM\0size\0", TVAL_PTR).ptrval;
509		if (!size) {
510			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);
511		}
512		state->info->save_size = atoi(size);
513		if (!state->info->save_size) {
514			fatal_error("EEPROM size %s is invalid\n", size);
515		}
516		char *etype = tern_find_path(state->root, "EEPROM\0type\0", TVAL_PTR).ptrval;
517		if (!etype) {
518			etype = "i2c";
519		}
520		if (!strcmp(etype, "i2c")) {
521			state->info->save_type = SAVE_I2C;
522		} else {
523			fatal_error("EEPROM type %s is invalid\n", etype);
524		}
525		state->info->save_buffer = malloc(state->info->save_size);
526		memset(state->info->save_buffer, 0xFF, state->info->save_size);
527		state->info->eeprom_map = malloc(sizeof(eeprom_map) * state->num_els);
528		memset(state->info->eeprom_map, 0, sizeof(eeprom_map) * state->num_els);
529	}
530}
531
532void process_nor_def(char *key, map_iter_state *state)
533{
534	if (!state->info->save_size) {
535		char *size = tern_find_path(state->root, "NOR\0size\0", TVAL_PTR).ptrval;
536		if (!size) {
537			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR size is not defined\n", state->index, key);
538		}
539		state->info->save_size = atoi(size);
540		if (!state->info->save_size) {
541			fatal_error("NOR size %s is invalid\n", size);
542		}
543		char *page_size = tern_find_path(state->root, "NOR\0page_size\0", TVAL_PTR).ptrval;
544		if (!page_size) {
545			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR page size is not defined\n", state->index, key);
546		}
547		uint32_t save_page_size = atoi(page_size);
548		if (!save_page_size) {
549			fatal_error("NOR page size %s is invalid\n", page_size);
550		}
551		char *product_id = tern_find_path(state->root, "NOR\0product_id\0", TVAL_PTR).ptrval;
552		if (!product_id) {
553			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR product ID is not defined\n", state->index, key);
554		}
555		uint16_t save_product_id = strtol(product_id, NULL, 16);
556		char *bus = tern_find_path(state->root, "NOR\0bus\0", TVAL_PTR).ptrval;
557		if (!strcmp(bus, "odd")) {
558			state->info->save_bus = RAM_FLAG_ODD;
559		} else if(!strcmp(bus, "even")) {
560			state->info->save_bus = RAM_FLAG_EVEN;
561		} else {
562			state->info->save_bus = RAM_FLAG_BOTH;
563		}
564		state->info->save_type = SAVE_NOR;
565		state->info->save_buffer = malloc(state->info->save_size);
566		char *init = tern_find_path_default(state->root, "NOR\0init\0", (tern_val){.ptrval="FF"}, TVAL_PTR).ptrval;
567		if (!strcmp(init, "ROM")) {
568			uint32_t init_size = state->rom_size > state->info->save_size ? state->info->save_size : state->rom_size;
569			memcpy(state->info->save_buffer, state->rom, init_size);
570			if (state->info->save_bus == RAM_FLAG_BOTH) {
571				byteswap_rom(state->info->save_size, (uint16_t *)state->info->save_buffer);
572			}
573		} else {
574			memset(state->info->save_buffer, strtol(init, NULL, 16), state->info->save_size);
575		}
576		state->info->nor = calloc(1, sizeof(nor_state));
577		nor_flash_init(state->info->nor, state->info->save_buffer, state->info->save_size, save_page_size, save_product_id, state->info->save_bus);
578		char *cmd1 = tern_find_path(state->root, "NOR\0cmd_address1\0", TVAL_PTR).ptrval;
579		if (cmd1) {
580			state->info->nor->cmd_address1 = strtol(cmd1, NULL, 16);
581		}
582		char *cmd2 = tern_find_path(state->root, "NOR\0cmd_address2\0", TVAL_PTR).ptrval;
583		if (cmd2) {
584			state->info->nor->cmd_address2 = strtol(cmd2, NULL, 16);
585		}
586	}
587}
588
589void add_eeprom_map(tern_node *node, uint32_t start, uint32_t end, map_iter_state *state)
590{
591	eeprom_map *eep_map = state->info->eeprom_map + state->info->num_eeprom;
592	eep_map->start = start;
593	eep_map->end = end;
594	eep_map->sda_read_bit = 0xFF;
595	tern_node * bits_read = tern_find_node(node, "bits_read");
596	if (bits_read) {
597		tern_foreach(bits_read, eeprom_read_fun, eep_map);
598	}
599	tern_node * bits_write = tern_find_node(node, "bits_write");
600	if (bits_write) {
601		tern_foreach(bits_write, eeprom_write_fun, eep_map);
602	}
603	debug_message("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);
604	state->info->num_eeprom++;
605}
606
607void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
608{
609	map_iter_state *state = data;
610	if (valtype != TVAL_NODE) {
611		fatal_error("ROM DB map entry %d with address %s is not a node\n", state->index, key);
612	}
613	tern_node *node = val.ptrval;
614	uint32_t start = strtol(key, NULL, 16);
615	uint32_t end = strtol(tern_find_ptr_default(node, "last", "0"), NULL, 16);
616	if (!end || end < start) {
617		fatal_error("'last' value is missing or invalid for ROM DB map entry %d with address %s\n", state->index, key);
618	}
619	char * dtype = tern_find_ptr_default(node, "device", "ROM");
620	uint32_t offset = strtol(tern_find_ptr_default(node, "offset", "0"), NULL, 16);
621	memmap_chunk *map = state->info->map + state->index;
622	map->start = start;
623	map->end = end + 1;
624	if (!strcmp(dtype, "ROM")) {
625		map->buffer = state->rom + offset;
626		map->mask = calc_mask(state->rom_size - offset, start, end);
627		if (strcmp(tern_find_ptr_default(node, "writeable", "no"), "yes")) {
628			map->flags = MMAP_READ;
629		} else {
630			map->flags = MMAP_READ | MMAP_WRITE | MMAP_CODE;
631		}
632	} else if (!strcmp(dtype, "LOCK-ON")) {
633		rom_info lock_info;
634		if (state->lock_on) {
635			lock_info = configure_rom(state->rom_db, state->lock_on, state->lock_on_size, NULL, 0, NULL, 0);
636		} else if (state->rom_size > start) {
637			//This is a bit of a hack to deal with pre-combined S3&K/S2&K ROMs and S&K ROM hacks
638			lock_info = configure_rom(state->rom_db, state->rom + start, state->rom_size - start, NULL, 0, NULL, 0);
639		} else {
640			//skip this entry if there is no lock on cartridge attached
641			return;
642		}
643		uint32_t matching_chunks = 0;
644		for (int i = 0; i < lock_info.map_chunks; i++)
645		{
646			if (lock_info.map[i].start < 0xC00000 && lock_info.map[i].end > 0x200000) {
647				matching_chunks++;
648			}
649		}
650		if (matching_chunks == 0) {
651			//Nothing mapped in the relevant range for the lock-on cart, ignore this mapping
652			free_rom_info(&lock_info);
653			return;
654		} else if (matching_chunks > 1) {
655			state->info->map_chunks += matching_chunks - 1;
656			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
657			memset(state->info->map + state->info->map_chunks - (matching_chunks - 1), 0, sizeof(memmap_chunk) * (matching_chunks - 1));
658			map = state->info->map + state->index;
659		}
660		for (int i = 0; i < lock_info.map_chunks; i++)
661		{
662			if (lock_info.map[i].start >= 0xC00000 || lock_info.map[i].end <= 0x200000) {
663				continue;
664			}
665			*map = lock_info.map[i];
666			if (map->start < 0x200000) {
667				if (map->buffer) {
668					map->buffer += (0x200000 - map->start) & ((map->flags & MMAP_AUX_BUFF) ? map->aux_mask : map->mask);
669				}
670				map->start = 0x200000;
671			}
672			map++;
673			state->index++;
674		}
675		if (state->info->save_type == SAVE_NONE && lock_info.save_type != SAVE_NONE) {
676			//main cart has no save device, but lock-on cart does
677			if (state->lock_on) {
678				state->info->is_save_lock_on = 1;
679			}
680			state->info->save_buffer = lock_info.save_buffer;
681			state->info->save_size = lock_info.save_size;
682			state->info->save_mask = lock_info.save_mask;
683			state->info->nor = lock_info.nor;
684			state->info->save_type = lock_info.save_type;
685			state->info->save_bus = lock_info.save_bus;
686			lock_info.save_buffer = NULL;
687			lock_info.save_type = SAVE_NONE;
688		}
689		free_rom_info(&lock_info);
690		return;
691	} else if (!strcmp(dtype, "EEPROM")) {
692		process_eeprom_def(key, state);
693		add_eeprom_map(node, start, end, state);
694
695		map->write_16 = write_eeprom_i2c_w;
696		map->write_8 = write_eeprom_i2c_b;
697		map->read_16 = read_eeprom_i2c_w;
698		map->read_8 = read_eeprom_i2c_b;
699		map->mask = 0xFFFFFF;
700	} else if (!strcmp(dtype, "SRAM")) {
701		process_sram_def(key, state);
702		map->buffer = state->info->save_buffer + offset;
703		map->flags = MMAP_READ | MMAP_WRITE;
704		if (state->info->save_type == RAM_FLAG_ODD) {
705			map->flags |= MMAP_ONLY_ODD;
706		} else if(state->info->save_type == RAM_FLAG_EVEN) {
707			map->flags |= MMAP_ONLY_EVEN;
708		}
709		map->mask = calc_mask(state->info->save_size, start, end);
710	} else if (!strcmp(dtype, "RAM")) {
711		uint32_t size = strtol(tern_find_ptr_default(node, "size", "0"), NULL, 16);
712		if (!size || size > map->end - map->start) {
713			size = map->end - map->start;
714		}
715		map->buffer = malloc(size);
716		map->mask = calc_mask(size, start, end);
717		map->flags = MMAP_READ | MMAP_WRITE;
718		char *bus = tern_find_ptr_default(node, "bus", "both");
719		if (!strcmp(bus, "odd")) {
720			map->flags |= MMAP_ONLY_ODD;
721		} else if (!strcmp(bus, "even")) {
722			map->flags |= MMAP_ONLY_EVEN;
723		} else {
724			map->flags |= MMAP_CODE;
725		}
726	} else if (!strcmp(dtype, "NOR")) {
727		process_nor_def(key, state);
728		
729		map->write_16 = nor_flash_write_w;
730		map->write_8 = nor_flash_write_b;
731		map->read_16 = nor_flash_read_w;
732		map->read_8 = nor_flash_read_b;
733		if (state->info->save_bus == RAM_FLAG_BOTH) {
734			map->flags |= MMAP_READ_CODE | MMAP_CODE;
735			map->buffer = state->info->save_buffer;
736		}
737		map->mask = 0xFFFFFF;
738	} else if (!strcmp(dtype, "Sega mapper")) {
739		state->info->mapper_type = MAPPER_SEGA;
740		state->info->mapper_start_index = state->ptr_index++;
741		char *variant = tern_find_ptr_default(node, "variant", "full");
742		char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
743		if (save_device && !strcmp(save_device, "EEPROM")) {
744			process_eeprom_def(key, state);
745			add_eeprom_map(node, start & map->mask, end & map->mask, state);
746		} else if (save_device && !strcmp(save_device, "SRAM")) {
747			process_sram_def(key, state);
748		} else if(has_ram_header(state->rom, state->rom_size)) {
749			//no save definition in ROM DB entry, but there is an SRAM header
750			//this support is mostly to handle homebrew that uses the SSF2 product ID
751			//in an attempt to signal desire for the full Sega/SSF2 mapper, but also uses SRAM unlike SSF2
752			read_ram_header(state->info, state->rom);
753		}
754		if (!strcmp(variant, "save-only")) {
755			state->info->map_chunks+=1;
756			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
757			memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
758			map = state->info->map + state->index;
759			map->start = start;
760			map->end = end;
761			offset &= nearest_pow2(state->rom_size) - 1;
762			map->buffer = state->rom + offset;
763			map->mask = calc_mask(state->rom_size - offset, start, end);
764			map->ptr_index = state->info->mapper_start_index;
765			map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
766			if (save_device && !strcmp(save_device, "EEPROM")) {
767				map->write_16 = write_eeprom_i2c_w;
768				map->write_8 = write_eeprom_i2c_b;
769				map->read_16 = read_eeprom_i2c_w;
770				map->read_8 = read_eeprom_i2c_b;
771			} else {
772				map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[ptr_idx] == NULL
773				map->read_8 = (read_8_fun)read_sram_b;
774				map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
775				map->write_8 = (write_8_fun)write_sram_area_b;
776			}
777			state->index++;
778			map++;
779		} else {
780			state->info->map_chunks+=7;
781			state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
782			memset(state->info->map + state->info->map_chunks - 7, 0, sizeof(memmap_chunk) * 7);
783			map = state->info->map + state->index;
784			for (int i = 0; i < 7; i++, state->index++, map++)
785			{
786				map->start = start + i * 0x80000;
787				map->end = start + (i + 1) * 0x80000;
788				map->mask = 0x7FFFF;
789				map->buffer = state->rom + offset + i * 0x80000;
790				map->ptr_index = state->ptr_index++;
791				if (i < 3) {
792					map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
793				} else {
794					map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
795					if (save_device && !strcmp(save_device, "EEPROM")) {
796						map->write_16 = write_eeprom_i2c_w;
797						map->write_8 = write_eeprom_i2c_b;
798						map->read_16 = read_eeprom_i2c_w;
799						map->read_8 = read_eeprom_i2c_b;
800					} else {
801						map->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[2] == NULL
802						map->read_8 = (read_8_fun)read_sram_b;
803						map->write_16 = (write_16_fun)write_sram_area_w;//these will be called all writes to the area
804						map->write_8 = (write_8_fun)write_sram_area_b;
805					}
806				}
807			}
808		}
809		map->start = 0xA13000;
810		map->end = 0xA13100;
811		map->mask = 0xFF;
812		map->write_16 = (write_16_fun)write_bank_reg_w;
813		map->write_8 = (write_8_fun)write_bank_reg_b;
814	} else if (!strcmp(dtype, "MENU")) {
815		//fake hardware for supporting menu
816		map->buffer = NULL;
817		map->mask = 0xFF;
818		map->write_16 = menu_write_w;
819		map->read_16 = menu_read_w;
820	} else if (!strcmp(dtype, "fixed")) {
821		uint16_t *value =  malloc(2);
822		map->buffer = value;
823		map->mask = 0;
824		map->flags = MMAP_READ;
825		*value = strtol(tern_find_ptr_default(node, "value", "0"), NULL, 16);
826	} else if (!strcmp(dtype, "multi-game")) {
827		state->info->mapper_type = MAPPER_MULTI_GAME;
828		state->info->mapper_start_index = state->ptr_index++;
829		//make a mirror copy of the ROM so we can efficiently support arbitrary start offsets
830		state->rom = realloc(state->rom, state->rom_size * 2);
831		memcpy(state->rom + state->rom_size, state->rom, state->rom_size);
832		state->rom_size *= 2;
833		//make room for an extra map entry
834		state->info->map_chunks+=1;
835		state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
836		memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
837		map = state->info->map + state->index;
838		map->buffer = state->rom;
839		map->mask = calc_mask(state->rom_size, start, end);
840		map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
841		map->ptr_index = state->info->mapper_start_index;
842		map++;
843		state->index++;
844		map->start = 0xA13000;
845		map->end = 0xA13100;
846		map->mask = 0xFF;
847		map->write_16 = write_multi_game_w;
848		map->write_8 = write_multi_game_b;
849	} else if (!strcmp(dtype, "megawifi")) {
850		if (!strcmp(
851			"on", 
852			tern_find_path_default(config, "system\0megawifi\0", (tern_val){.ptrval="off"}, TVAL_PTR).ptrval)
853		) {
854			map->write_16 = megawifi_write_w;
855			map->write_8 = megawifi_write_b;
856			map->read_16 = megawifi_read_w;
857			map->read_8 = megawifi_read_b;
858			map->mask = 0xFFFFFF;
859		} else {
860			warning("ROM uses MegaWiFi, but it is disabled\n");
861			return;
862		}
863	} else if (!strcmp(dtype, "jcart")) {
864		state->info->mapper_type = MAPPER_JCART;
865		map->write_16 = jcart_write_w;
866		map->write_8 = jcart_write_b;
867		map->read_16 = jcart_read_w;
868		map->read_8 = jcart_read_b;
869		map->mask = 0xFFFFFF;
870	} else {
871		fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
872	}
873	state->index++;
874}
875
876rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *lock_on, uint32_t lock_on_size, memmap_chunk const *base_map, uint32_t base_chunks)
877{
878	uint8_t product_id[GAME_ID_LEN+1];
879	uint8_t *rom = vrom;
880	product_id[GAME_ID_LEN] = 0;
881	for (int i = 0; i < GAME_ID_LEN; i++)
882	{
883		if (rom[GAME_ID_OFF + i] <= ' ') {
884			product_id[i] = 0;
885			break;
886		}
887		product_id[i] = rom[GAME_ID_OFF + i];
888
889	}
890	debug_message("Product ID: %s\n", product_id);
891	uint8_t raw_hash[20];
892	sha1(vrom, rom_size, raw_hash);
893	uint8_t hex_hash[41];
894	bin_to_hex(hex_hash, raw_hash, 20);
895	debug_message("SHA1: %s\n", hex_hash);
896	tern_node * entry = tern_find_node(rom_db, hex_hash);
897	if (!entry) {
898		entry = tern_find_node(rom_db, product_id);
899	}
900	if (!entry) {
901		debug_message("Not found in ROM DB, examining header\n\n");
902		if (xband_detect(rom, rom_size)) {
903			return xband_configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, base_chunks);
904		}
905		if (realtec_detect(rom, rom_size)) {
906			return realtec_configure_rom(rom, rom_size, base_map, base_chunks);
907		}
908		return configure_rom_heuristics(rom, rom_size, base_map, base_chunks);
909	}
910	rom_info info;
911	info.mapper_type = MAPPER_NONE;
912	info.name = tern_find_ptr(entry, "name");
913	if (info.name) {
914		debug_message("Found name: %s\n\n", info.name);
915		info.name = strdup(info.name);
916	} else {
917		info.name = get_header_name(rom);
918	}
919
920	char *dbreg = tern_find_ptr(entry, "regions");
921	info.regions = 0;
922	if (dbreg) {
923		while (*dbreg != 0)
924		{
925			info.regions |= translate_region_char(*(dbreg++));
926		}
927	}
928	if (!info.regions) {
929		info.regions = get_header_regions(rom);
930	}
931
932	info.is_save_lock_on = 0;
933	info.rom = vrom;
934	info.rom_size = rom_size;
935	tern_node *map = tern_find_node(entry, "map");
936	if (map) {
937		info.save_type = SAVE_NONE;
938		info.map_chunks = tern_count(map);
939		if (info.map_chunks) {
940			info.map_chunks += base_chunks;
941			info.save_buffer = NULL;
942			info.save_size = 0;
943			info.map = malloc(sizeof(memmap_chunk) * info.map_chunks);
944			info.eeprom_map = NULL;
945			info.num_eeprom = 0;
946			memset(info.map, 0, sizeof(memmap_chunk) * info.map_chunks);
947			map_iter_state state = {
948				.info = &info, 
949				.rom = rom, 
950				.lock_on = lock_on,
951				.root = entry,
952				.rom_db = rom_db,
953				.rom_size = rom_size, 
954				.lock_on_size = lock_on_size,
955				.index = 0, 
956				.num_els = info.map_chunks - base_chunks,
957				.ptr_index = 0
958			};
959			tern_foreach(map, map_iter_fun, &state);
960			memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);
961			info.rom = state.rom;
962			info.rom_size = state.rom_size;
963		} else {
964			add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
965		}
966	} else {
967		add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
968	}
969
970	tern_node *device_overrides = tern_find_node(entry, "device_overrides");
971	if (device_overrides) {
972		info.port1_override = tern_find_ptr(device_overrides, "1");
973		info.port2_override = tern_find_ptr(device_overrides, "2");
974		info.ext_override = tern_find_ptr(device_overrides, "ext");
975	} else {
976		info.port1_override = info.port2_override = info.ext_override = NULL;
977	}
978	info.mouse_mode = tern_find_ptr(entry, "mouse_mode");
979
980	return info;
981}