changeset 1141:7e199bebde2f

Initial support for Sega's family of SMS mappers
author Michael Pavone <pavone@retrodev.com>
date Mon, 02 Jan 2017 22:54:24 -0800
parents 4490c9c12272
children 5c8b1c33ca10
files sms.c sms.h
diffstat 2 files changed, 54 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/sms.c	Mon Jan 02 21:46:26 2017 -0800
+++ b/sms.c	Mon Jan 02 22:54:24 2017 -0800
@@ -97,6 +97,32 @@
 	return 0xFF;
 }
 
+static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
+{
+	z80_context *z80 = vcontext;
+	sms_context *sms = z80->system;
+	sms->ram[location & (sizeof(sms->ram)-1)] = value;
+	switch (location & 3)
+	{
+	case 0:
+		//TODO: implement me
+		break;
+	case 1:
+		z80->mem_pointers[0] = sms->rom + (value << 14 & (sms->rom_size-1)) + 0x400;
+		//TODO: invalidate translated code in range 0x400-0x4000
+		break;
+	case 2:
+		z80->mem_pointers[1] = sms->rom + (value << 14 & (sms->rom_size-1));
+		//TODO: invalidate translated code in range 0x4000-0x8000
+		break;
+	case 3:
+		z80->mem_pointers[2] = sms->rom + (value << 14 & (sms->rom_size-1));
+		//TODO: invalidate translated code in range 0x8000-0xC000
+		break;
+	}
+	return vcontext;
+}
+
 static memmap_chunk io_map[] = {
 	{0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL,     memory_io_write},
 	{0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read,  sms_psg_write},
@@ -202,19 +228,38 @@
 {
 	memset(info_out, 0, sizeof(*info_out));
 	sms_context *sms = calloc(1, sizeof(sms_context));
+	uint32_t orig_size = rom_size;
 	rom_size = nearest_pow2(rom_size);
-	uint32_t mask = rom_size >= 0xC000 ? 0xFFFF : rom_size-1;
-	memmap_chunk memory_map[] = {
-		{0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      rom,      NULL, NULL, NULL, NULL},
-		{0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL}
+	memmap_chunk memory_map[6];
+	if (orig_size > 0xC000)  {
+		info_out->map_chunks = 6;
+		uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
+		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF,             0, 0, MMAP_READ,                      rom,      NULL, NULL, NULL, NULL};
+		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
+		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
+		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX,         NULL,     NULL, NULL, NULL, NULL};
+		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
+		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0xFFFF,             0, 0, MMAP_READ,                      ram_reg_overlap, NULL, NULL, NULL, mapper_write};
+	} else {
+		info_out->map_chunks = 2;
+		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      rom,      NULL, NULL, NULL, NULL};
+		memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL};
 	};
-	info_out->map = malloc(sizeof(memory_map));
-	memcpy(info_out->map, memory_map, sizeof(memory_map));
+	info_out->map = malloc(sizeof(memmap_chunk) * info_out->map_chunks);
+	memcpy(info_out->map, memory_map, sizeof(memmap_chunk) * info_out->map_chunks);
 	z80_options *zopts = malloc(sizeof(z80_options));
-	init_z80_opts(zopts, info_out->map, 2, io_map, 4, 15, 0xFF);
+	init_z80_opts(zopts, info_out->map, info_out->map_chunks, io_map, 4, 15, 0xFF);
 	sms->z80 = init_z80_context(zopts);
 	sms->z80->system = sms;
 	
+	sms->rom = rom;
+	sms->rom_size = rom_size;
+	if (info_out->map_chunks > 2) {
+		sms->z80->mem_pointers[0] = sms->rom;
+		sms->z80->mem_pointers[1] = sms->rom + 0x4000;
+		sms->z80->mem_pointers[2] = sms->rom + 0x8000;
+	}
+	
 	char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval;
 	uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390;
 	
--- a/sms.h	Mon Jan 02 21:46:26 2017 -0800
+++ b/sms.h	Mon Jan 02 22:54:24 2017 -0800
@@ -15,6 +15,8 @@
 	vdp_context   *vdp;
 	psg_context   *psg;
 	sega_io       io;
+	uint8_t       *rom;
+	uint32_t      rom_size;
 	uint32_t      master_clock;
 	uint32_t      normal_clock;
 	uint8_t       should_return;