comparison sms.c @ 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 8f14767661fa
children 5c8b1c33ca10
comparison
equal deleted inserted replaced
1140:4490c9c12272 1141:7e199bebde2f
93 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle); 93 uint8_t port_a = io_data_read(sms->io.ports, z80->current_cycle);
94 uint8_t port_b = io_data_read(sms->io.ports, z80->current_cycle); 94 uint8_t port_b = io_data_read(sms->io.ports, z80->current_cycle);
95 return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10; 95 return (port_a & 0x40) | (port_b >> 2 & 0xF) | (port_b << 1 & 0x80) | 0x10;
96 } 96 }
97 return 0xFF; 97 return 0xFF;
98 }
99
100 static void *mapper_write(uint32_t location, void *vcontext, uint8_t value)
101 {
102 z80_context *z80 = vcontext;
103 sms_context *sms = z80->system;
104 sms->ram[location & (sizeof(sms->ram)-1)] = value;
105 switch (location & 3)
106 {
107 case 0:
108 //TODO: implement me
109 break;
110 case 1:
111 z80->mem_pointers[0] = sms->rom + (value << 14 & (sms->rom_size-1)) + 0x400;
112 //TODO: invalidate translated code in range 0x400-0x4000
113 break;
114 case 2:
115 z80->mem_pointers[1] = sms->rom + (value << 14 & (sms->rom_size-1));
116 //TODO: invalidate translated code in range 0x4000-0x8000
117 break;
118 case 3:
119 z80->mem_pointers[2] = sms->rom + (value << 14 & (sms->rom_size-1));
120 //TODO: invalidate translated code in range 0x8000-0xC000
121 break;
122 }
123 return vcontext;
98 } 124 }
99 125
100 static memmap_chunk io_map[] = { 126 static memmap_chunk io_map[] = {
101 {0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL, memory_io_write}, 127 {0x00, 0x40, 0xFF, 0, 0, 0, NULL, NULL, NULL, NULL, memory_io_write},
102 {0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read, sms_psg_write}, 128 {0x40, 0x80, 0xFF, 0, 0, 0, NULL, NULL, NULL, hv_read, sms_psg_write},
200 226
201 sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom, uint32_t extra_rom_size, uint32_t opts, uint8_t force_region, rom_info *info_out) 227 sms_context *alloc_configure_sms(void *rom, uint32_t rom_size, void *extra_rom, uint32_t extra_rom_size, uint32_t opts, uint8_t force_region, rom_info *info_out)
202 { 228 {
203 memset(info_out, 0, sizeof(*info_out)); 229 memset(info_out, 0, sizeof(*info_out));
204 sms_context *sms = calloc(1, sizeof(sms_context)); 230 sms_context *sms = calloc(1, sizeof(sms_context));
231 uint32_t orig_size = rom_size;
205 rom_size = nearest_pow2(rom_size); 232 rom_size = nearest_pow2(rom_size);
206 uint32_t mask = rom_size >= 0xC000 ? 0xFFFF : rom_size-1; 233 memmap_chunk memory_map[6];
207 memmap_chunk memory_map[] = { 234 if (orig_size > 0xC000) {
208 {0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, rom, NULL, NULL, NULL, NULL}, 235 info_out->map_chunks = 6;
209 {0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, MMAP_READ|MMAP_WRITE|MMAP_CODE, sms->ram, NULL, NULL, NULL, NULL} 236 uint8_t *ram_reg_overlap = sms->ram + sizeof(sms->ram) - 4;
237 memory_map[0] = (memmap_chunk){0x0000, 0x0400, 0xFFFF, 0, 0, MMAP_READ, rom, NULL, NULL, NULL, NULL};
238 memory_map[1] = (memmap_chunk){0x0400, 0x4000, 0xFFFF, 0, 0, MMAP_READ|MMAP_PTR_IDX, NULL, NULL, NULL, NULL, NULL};
239 memory_map[2] = (memmap_chunk){0x4000, 0x8000, 0x3FFF, 0, 1, MMAP_READ|MMAP_PTR_IDX, NULL, NULL, NULL, NULL, NULL};
240 memory_map[3] = (memmap_chunk){0x8000, 0xC000, 0x3FFF, 0, 2, MMAP_READ|MMAP_PTR_IDX, NULL, NULL, NULL, NULL, NULL};
241 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};
242 memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0xFFFF, 0, 0, MMAP_READ, ram_reg_overlap, NULL, NULL, NULL, mapper_write};
243 } else {
244 info_out->map_chunks = 2;
245 memory_map[0] = (memmap_chunk){0x0000, 0xC000, rom_size-1, 0, 0, MMAP_READ, rom, NULL, NULL, NULL, NULL};
246 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};
210 }; 247 };
211 info_out->map = malloc(sizeof(memory_map)); 248 info_out->map = malloc(sizeof(memmap_chunk) * info_out->map_chunks);
212 memcpy(info_out->map, memory_map, sizeof(memory_map)); 249 memcpy(info_out->map, memory_map, sizeof(memmap_chunk) * info_out->map_chunks);
213 z80_options *zopts = malloc(sizeof(z80_options)); 250 z80_options *zopts = malloc(sizeof(z80_options));
214 init_z80_opts(zopts, info_out->map, 2, io_map, 4, 15, 0xFF); 251 init_z80_opts(zopts, info_out->map, info_out->map_chunks, io_map, 4, 15, 0xFF);
215 sms->z80 = init_z80_context(zopts); 252 sms->z80 = init_z80_context(zopts);
216 sms->z80->system = sms; 253 sms->z80->system = sms;
254
255 sms->rom = rom;
256 sms->rom_size = rom_size;
257 if (info_out->map_chunks > 2) {
258 sms->z80->mem_pointers[0] = sms->rom;
259 sms->z80->mem_pointers[1] = sms->rom + 0x4000;
260 sms->z80->mem_pointers[2] = sms->rom + 0x8000;
261 }
217 262
218 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval; 263 char * lowpass_cutoff_str = tern_find_path(config, "audio\0lowpass_cutoff\0").ptrval;
219 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390; 264 uint32_t lowpass_cutoff = lowpass_cutoff_str ? atoi(lowpass_cutoff_str) : 3390;
220 265
221 //TODO: Detect region and pick master clock based off of that 266 //TODO: Detect region and pick master clock based off of that