summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Pavone <pavone@retrodev.com>2017-06-22 23:40:05 -0700
committerMichael Pavone <pavone@retrodev.com>2017-06-22 23:40:05 -0700
commite7e41dd4b314ce34c2c4f1152d243b606ded8565 (patch)
treea468d4f140f388beca285168b49026a1d4f20bc6
parentbabdbb88c01875362875c9b0ef2e3930f8ce97c3 (diff)
Sonic 3 & Knuckles lock-on is now 100% functional with working saves
-rw-r--r--genesis.h1
-rw-r--r--rom.db20
-rw-r--r--romdb.c83
3 files changed, 79 insertions, 25 deletions
diff --git a/genesis.h b/genesis.h
index 80536ec..f2a0a5c 100644
--- a/genesis.h
+++ b/genesis.h
@@ -32,6 +32,7 @@ struct genesis_context {
uint8_t *zram;
void *extra;
uint8_t *save_storage;
+ void *mapper_temp;
eeprom_map *eeprom_map;
uint32_t num_eeprom;
uint32_t save_size;
diff --git a/rom.db b/rom.db
index 7f59084..e920074 100644
--- a/rom.db
+++ b/rom.db
@@ -433,6 +433,26 @@ T-12053 {
}
}
}
+MK-1079 {
+ #This entry is needed only to make this play nicely with
+ #S&K lock-on support. Normal 2MB cartridges with SRAM won't
+ #work right, but Sonic 3 has the limited SRAM-only variant
+ #of Sega's mapper commonly found on 4MB carts with SRAM
+ name Sonic the Hedgehog 3
+ map {
+ 0 {
+ device ROM
+ last 1FFFFF
+ }
+ 200000 {
+ device Sega mapper
+ variant save-only
+ offset 200000
+ last 3FFFFF
+ }
+ }
+
+}
MK-1563 {
name Sonic & Knuckles
map {
diff --git a/romdb.c b/romdb.c
index 211d4c4..51fcf51 100644
--- a/romdb.c
+++ b/romdb.c
@@ -494,6 +494,9 @@ m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16
if (!address) {
if (value & 1) {
//Used for games that only use the mapper for SRAM
+ if (context->mem_pointers[gen->mapper_start_index]) {
+ gen->mapper_temp = context->mem_pointers[gen->mapper_start_index];
+ }
context->mem_pointers[gen->mapper_start_index] = NULL;
//For games that need more than 4MB
for (int i = 4; i < 8; i++)
@@ -502,7 +505,9 @@ m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16
}
} else {
//Used for games that only use the mapper for SRAM
- context->mem_pointers[gen->mapper_start_index] = gen->cart + 0x200000/2;
+ if (!context->mem_pointers[gen->mapper_start_index]) {
+ context->mem_pointers[gen->mapper_start_index] = gen->mapper_temp;
+ }
//For games that need more than 4MB
for (int i = 4; i < 8; i++)
{
@@ -1094,7 +1099,7 @@ void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
memset(state->info->map + state->info->map_chunks - (matching_chunks - 1), 0, sizeof(memmap_chunk) * (matching_chunks - 1));
map = state->info->map + state->index;
}
- for (int i = 0; i < matching_chunks; i++)
+ for (int i = 0; i < lock_info.map_chunks; i++)
{
if (lock_info.map[i].start >= 0xC00000 || lock_info.map[i].end <= 0x200000) {
continue;
@@ -1171,10 +1176,7 @@ void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
map->mask = 0xFFFFFF;
} else if (!strcmp(dtype, "Sega mapper")) {
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 *variant = tern_find_ptr_default(node, "variant", "full");
char *save_device = tern_find_path(node, "save\0device\0", TVAL_PTR).ptrval;
if (save_device && !strcmp(save_device, "EEPROM")) {
process_eeprom_def(key, state);
@@ -1187,27 +1189,58 @@ void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
//in an attempt to signal desire for the full Sega/SSF2 mapper, but also uses SRAM unlike SSF2
read_ram_header(state->info, state->rom);
}
- 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) {
- map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
+ if (!strcmp(variant, "save-only")) {
+ 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->start = start;
+ map->end = end;
+ offset &= nearest_pow2(state->rom_size) - 1;
+ map->buffer = state->rom + offset;
+ map->mask = calc_mask(state->rom_size - offset, start, end);
+ map->ptr_index = state->info->mapper_start_index;
+ map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
+ if (save_device && !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;
} else {
- map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
- if (save_device && !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->read_16 = (read_16_fun)read_sram_w;//these will only be called when mem_pointers[ptr_idx] == 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;
+ }
+ state->index++;
+ map++;
+ } else {
+ 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;
+ 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) {
+ map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE;
} else {
- 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;
+ map->flags = MMAP_READ | MMAP_PTR_IDX | MMAP_CODE | MMAP_FUNC_NULL;
+ if (save_device && !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;
+ } else {
+ 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;
+ }
}
}
}