Mercurial > repos > blastem
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 |