summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2017-06-24 13:55:54 -0700
committerMichael Pavone <pavone@retrodev.com>2017-06-24 13:55:54 -0700
commitc21c73853ca656be57011cdb0c2e7b9da1dac5df (patch)
tree7166ac77cecb7a046803eaa3d89d1c9f9815e493
parent9619ce0a27ca9509a9c86f156f411258a17e085f (diff)
Support a couple of bootleg X-in-1 carts
-rw-r--r--Makefile2
-rw-r--r--genesis.c2
-rw-r--r--multi_game.c26
-rw-r--r--multi_game.h7
-rw-r--r--realtec.c3
-rw-r--r--rom.db20
-rw-r--r--romdb.c31
-rw-r--r--romdb.h2
-rw-r--r--xband.c3
9 files changed, 95 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index c27abee..d16ef71 100644
--- a/Makefile
+++ b/Makefile
@@ -127,7 +127,7 @@ Z80OBJS=z80inst.o z80_to_x86.o
AUDIOOBJS=ym2612.o psg.o wave.o
CONFIGOBJS=config.o tern.o util.o
-MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o sega_mapper.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
+MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o sega_mapper.o multi_game.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
ifeq ($(CPU),x86_64)
CFLAGS+=-DX86_64 -m64
diff --git a/genesis.c b/genesis.c
index 7ee975f..149b2a7 100644
--- a/genesis.c
+++ b/genesis.c
@@ -1170,6 +1170,8 @@ genesis_context *alloc_config_genesis(void *rom, uint32_t rom_size, void *lock_o
rom_db = load_rom_db();
}
*info_out = configure_rom(rom_db, rom, rom_size, lock_on, lock_on_size, base_map, sizeof(base_map)/sizeof(base_map[0]));
+ rom = info_out->rom;
+ rom_size = info_out->rom_size;
#ifndef BLASTEM_BIG_ENDIAN
byteswap_rom(rom_size, rom);
if (lock_on) {
diff --git a/multi_game.c b/multi_game.c
new file mode 100644
index 0000000..c00aada
--- /dev/null
+++ b/multi_game.c
@@ -0,0 +1,26 @@
+#include "genesis.h"
+
+void *write_multi_game_b(uint32_t address, void *vcontext, uint8_t value)
+{
+ m68k_context *context = vcontext;
+ genesis_context *gen = context->system;
+ uint32_t base = (address & 0x3F) << 16, start = 0, end = 0x400000;
+ //find the memmap chunk, so we can properly mask the base value
+ for (int i = 0; i < context->options->gen.memmap_chunks; i++)
+ {
+ if (context->options->gen.memmap[i].flags & MMAP_PTR_IDX) {
+ base &= context->options->gen.memmap[i].mask;
+ start = context->options->gen.memmap[i].start;
+ end = context->options->gen.memmap[i].end;
+ break;
+ }
+ }
+ context->mem_pointers[gen->mapper_start_index] = gen->cart + base/2;
+ m68k_invalidate_code_range(context, start, end);
+ return vcontext;
+}
+
+void *write_multi_game_w(uint32_t address, void *context, uint16_t value)
+{
+ return write_multi_game_b(address, context, value);
+}
diff --git a/multi_game.h b/multi_game.h
new file mode 100644
index 0000000..be0bfa3
--- /dev/null
+++ b/multi_game.h
@@ -0,0 +1,7 @@
+#ifndef MULTI_GAME_H_
+#define MULTI_GAME_H_
+
+void *write_multi_game_b(uint32_t address, void *context, uint8_t value);
+void *write_multi_game_w(uint32_t address, void *context, uint16_t value);
+
+#endif //MULTI_GAME_H_
diff --git a/realtec.c b/realtec.c
index babe1e2..de16dc5 100644
--- a/realtec.c
+++ b/realtec.c
@@ -102,6 +102,9 @@ rom_info realtec_configure_rom(uint8_t *rom, uint32_t rom_size, memmap_chunk con
info.save_buffer = NULL;
info.num_eeprom = 0;
info.eeprom_map = NULL;
+ info.rom = rom;
+ info.rom_size = rom_size;
+ info.is_save_lock_on = 0;
info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
info.map_chunks = base_chunks + 2;
info.map = calloc(sizeof(memmap_chunk), info.map_chunks);
diff --git a/rom.db b/rom.db
index e920074..6d92a54 100644
--- a/rom.db
+++ b/rom.db
@@ -942,3 +942,23 @@ BlstMenu {
}
}
}
+
+7313c20071de0ab1cd84ac1352cb0ed1c4a4afa8 {
+ #This appears to be an underdump, but it seems to be the only copy floating around
+ name 12-in-1
+ map {
+ 0 {
+ device multi-game
+ last 3FFFFF
+ }
+ }
+}
+6b2a6de2622735f6d56c6c9c01f74daa90e355cb {
+ name 15-in-1
+ map {
+ 0 {
+ device multi-game
+ last 3FFFFF
+ }
+ }
+}
diff --git a/romdb.c b/romdb.c
index b8b36fa..d621a2b 100644
--- a/romdb.c
+++ b/romdb.c
@@ -10,6 +10,7 @@
#include "realtec.h"
#include "nor.h"
#include "sega_mapper.h"
+#include "multi_game.h"
#define DOM_TITLE_START 0x120
#define DOM_TITLE_END 0x150
@@ -301,6 +302,9 @@ rom_info configure_rom_heuristics(uint8_t *rom, uint32_t rom_size, memmap_chunk
rom_info info;
info.name = get_header_name(rom);
info.regions = get_header_regions(rom);
+ info.is_save_lock_on = 0;
+ info.rom = rom;
+ info.rom_size = rom_size;
add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
return info;
@@ -681,6 +685,28 @@ void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
map->mask = 0;
map->flags = MMAP_READ;
*value = strtol(tern_find_ptr_default(node, "value", "0"), NULL, 16);
+ } else if (!strcmp(dtype, "multi-game")) {
+ state->info->mapper_start_index = state->ptr_index++;
+ //make a mirror copy of the ROM so we can efficiently support arbitrary start offsets
+ state->rom = realloc(state->rom, state->rom_size * 2);
+ memcpy(state->rom + state->rom_size, state->rom, state->rom_size);
+ state->rom_size *= 2;
+ //make room for an extra map entry
+ state->info->map_chunks+=1;
+ state->info->map = realloc(state->info->map, sizeof(memmap_chunk) * state->info->map_chunks);
+ memset(state->info->map + state->info->map_chunks - 1, 0, sizeof(memmap_chunk) * 1);
+ map = state->info->map + state->index;
+ map->buffer = state->rom;
+ map->mask = calc_mask(state->rom_size, start, end);
+ map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
+ map->ptr_index = state->info->mapper_start_index;
+ map++;
+ state->index++;
+ map->start = 0xA13000;
+ map->end = 0xA13100;
+ map->mask = 0xFF;
+ map->write_16 = write_multi_game_w;
+ map->write_8 = write_multi_game_b;
} else {
fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
}
@@ -742,6 +768,9 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *l
info.regions = get_header_regions(rom);
}
+ info.is_save_lock_on = 0;
+ info.rom = vrom;
+ info.rom_size = rom_size;
tern_node *map = tern_find_node(entry, "map");
if (map) {
info.save_type = SAVE_NONE;
@@ -768,6 +797,8 @@ rom_info configure_rom(tern_node *rom_db, void *vrom, uint32_t rom_size, void *l
};
tern_foreach(map, map_iter_fun, &state);
memcpy(info.map + state.index, base_map, sizeof(memmap_chunk) * base_chunks);
+ info.rom = state.rom;
+ info.rom_size = state.rom_size;
} else {
add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
}
diff --git a/romdb.h b/romdb.h
index 509a039..bc8f06e 100644
--- a/romdb.h
+++ b/romdb.h
@@ -46,6 +46,7 @@ struct rom_info {
char *name;
memmap_chunk *map;
uint8_t *save_buffer;
+ void *rom;
eeprom_map *eeprom_map;
char *port1_override;
char *port2_override;
@@ -53,6 +54,7 @@ struct rom_info {
char *mouse_mode;
uint32_t num_eeprom;
uint32_t map_chunks;
+ uint32_t rom_size;
uint32_t save_size;
uint32_t save_mask;
uint32_t save_page_size;
diff --git a/xband.c b/xband.c
index c5b1fc9..29d1498 100644
--- a/xband.c
+++ b/xband.c
@@ -313,6 +313,9 @@ rom_info xband_configure_rom(tern_node *rom_db, void *rom, uint32_t rom_size, vo
info.port2_override = strdup("xband keyboard");
info.eeprom_map = NULL;
info.num_eeprom = 0;
+ info.rom = rom;
+ info.rom_size = rom_size;
+ info.is_save_lock_on = 0;
xband *x = calloc(sizeof(xband), 1);
rom_size = nearest_pow2(rom_size);
for (int i = 0; (i + rom_size) <= sizeof(x->cart_space) / 2; i += rom_size)