# HG changeset patch # User Michael Pavone # Date 1483426464 28800 # Node ID 7e199bebde2f8aebe04411a8b0ab3c047f96e03b # Parent 4490c9c1227224d0c842075e8b7745feeace479d Initial support for Sega's family of SMS mappers diff -r 4490c9c12272 -r 7e199bebde2f sms.c --- 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; diff -r 4490c9c12272 -r 7e199bebde2f sms.h --- 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;