changeset 2134:9caebcfeac72

Implement word RAM interleaving in 1M mode, now passes mcd-verificator word RAM tests
author Michael Pavone <pavone@retrodev.com>
date Fri, 18 Mar 2022 20:49:07 -0700
parents 8554751f17b5
children 95b3752925e0
files backend.c backend_x86.c genesis.c memmap.h segacd.c segacd.h sms.c
diffstat 7 files changed, 217 insertions(+), 98 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Thu Mar 17 22:41:42 2022 -0700
+++ b/backend.c	Fri Mar 18 20:49:07 2022 -0700
@@ -96,11 +96,23 @@
 				: memmap[chunk].buffer;
 			if (!base) {
 				if (memmap[chunk].flags & MMAP_AUX_BUFF) {
-					return ((uint8_t *)memmap[chunk].buffer) + (address & memmap[chunk].aux_mask);
+					address &= memmap[chunk].aux_mask;
+					if (memmap[chunk].shift > 0) {
+						address <<= memmap[chunk].shift;
+					} else if (memmap[chunk].shift < 0) {
+						address >>= -memmap[chunk].shift;
+					}
+					return ((uint8_t *)memmap[chunk].buffer) + address;
 				}
 				return NULL;
 			}
-			return base + (address & memmap[chunk].mask);
+			address &= memmap[chunk].mask;
+			if (memmap[chunk].shift > 0) {
+				address <<= memmap[chunk].shift;
+			} else if (memmap[chunk].shift < 0) {
+				address >>= -memmap[chunk].shift;
+			}
+			return base + address;
 		}
 	}
 	return NULL;
@@ -121,11 +133,23 @@
 				: memmap[chunk].buffer;
 			if (!base) {
 				if (memmap[chunk].flags & MMAP_AUX_BUFF) {
-					return ((uint8_t *)memmap[chunk].buffer) + (address & memmap[chunk].aux_mask);
+					address &= memmap[chunk].aux_mask;
+					if (memmap[chunk].shift > 0) {
+						address <<= memmap[chunk].shift;
+					} else if (memmap[chunk].shift < 0) {
+						address >>= -memmap[chunk].shift;
+					}
+					return ((uint8_t *)memmap[chunk].buffer) + address;
 				}
 				return NULL;
 			}
-			return base + (address & memmap[chunk].mask);
+			address &= memmap[chunk].mask;
+			if (memmap[chunk].shift > 0) {
+				address <<= memmap[chunk].shift;
+			} else if (memmap[chunk].shift < 0) {
+				address >>= -memmap[chunk].shift;
+			}
+			return base + address;
 		}
 	}
 	return NULL;
@@ -147,6 +171,11 @@
 		}
 		if (base) {
 			uint16_t val;
+			if (chunk->shift > 0) {
+				offset <<= chunk->shift;
+			} else if (chunk->shift < 0){
+				offset >>= chunk->shift;
+			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				val = base[offset];
@@ -182,6 +211,11 @@
 			base = chunk->buffer;
 		}
 		if (base) {
+			if (chunk->shift > 0) {
+				offset <<= chunk->shift;
+			} else if (chunk->shift < 0){
+				offset >>= chunk->shift;
+			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				offset /= 2;
 				if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -214,6 +248,11 @@
 			base = chunk->buffer;
 		}
 		if (base) {
+			if (chunk->shift > 0) {
+				offset <<= chunk->shift;
+			} else if (chunk->shift < 0){
+				offset >>= chunk->shift;
+			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
@@ -250,6 +289,11 @@
 			base = chunk->buffer;
 		}
 		if (base) {
+			if (chunk->shift > 0) {
+				offset <<= chunk->shift;
+			} else if (chunk->shift < 0){
+				offset >>= chunk->shift;
+			}
 			if ((chunk->flags & MMAP_ONLY_ODD) || (chunk->flags & MMAP_ONLY_EVEN)) {
 				if (address & 1) {
 					if (chunk->flags & MMAP_ONLY_EVEN) {
--- a/backend_x86.c	Thu Mar 17 22:41:42 2022 -0700
+++ b/backend_x86.c	Fri Mar 18 20:49:07 2022 -0700
@@ -165,6 +165,29 @@
 		if (memmap[chunk].mask != opts->address_mask) {
 			and_ir(code, memmap[chunk].mask, adr_reg, opts->address_size);
 		}
+		code_ptr after_normal = NULL;
+		if (size == SZ_B && memmap[chunk].shift != 0) {
+			btr_ir(code, 0, adr_reg, opts->address_size);
+			code_ptr normal = code->cur+1;
+			jcc(code, CC_NC, normal);
+			if (memmap[chunk].shift > 0) {
+				shl_ir(code, memmap[chunk].shift, adr_reg, opts->address_size);
+			} else {
+				shr_ir(code, -memmap[chunk].shift, adr_reg, opts->address_size);
+			}
+			or_ir(code, 1, adr_reg, opts->address_size);
+			after_normal = code->cur + 1;
+			jmp(code, after_normal);
+			*normal = code->cur - (normal + 1);
+		}
+		if (memmap[chunk].shift > 0) {
+			shl_ir(code, memmap[chunk].shift, adr_reg, opts->address_size);
+		} else if (memmap[chunk].shift < 0) {
+			shr_ir(code, -memmap[chunk].shift, adr_reg, opts->address_size);
+		}
+		if (after_normal) {
+			*after_normal = code->cur - (after_normal + 1);
+		}
 		void * cfun;
 		switch (fun_type)
 		{
--- a/genesis.c	Thu Mar 17 22:41:42 2022 -0700
+++ b/genesis.c	Fri Mar 18 20:49:07 2022 -0700
@@ -1799,11 +1799,11 @@
 static genesis_context *shared_init(uint32_t system_opts, rom_info *rom, uint8_t force_region)
 {
 	static memmap_chunk z80_map[] = {
-		{ 0x0000, 0x4000,  0x1FFF, 0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL, NULL, NULL, NULL,              NULL },
-		{ 0x8000, 0x10000, 0x7FFF, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_bank,     z80_write_bank},
-		{ 0x4000, 0x6000,  0x0003, 0, 0, 0,                                  NULL, NULL, NULL, z80_read_ym,       z80_write_ym},
-		{ 0x6000, 0x6100,  0xFFFF, 0, 0, 0,                                  NULL, NULL, NULL, NULL,              z80_write_bank_reg},
-		{ 0x7F00, 0x8000,  0x00FF, 0, 0, 0,                                  NULL, NULL, NULL, z80_vdp_port_read, z80_vdp_port_write}
+		{ 0x0000, 0x4000,  0x1FFF, .flags = MMAP_READ | MMAP_WRITE | MMAP_CODE},
+		{ 0x8000, 0x10000, 0x7FFF, .read_8 = z80_read_bank, .write_8 = z80_write_bank},
+		{ 0x4000, 0x6000,  0x0003, .read_8 = z80_read_ym, .write_8 = z80_write_ym},
+		{ 0x6000, 0x6100,  0xFFFF, .write_8 = z80_write_bank_reg},
+		{ 0x7F00, 0x8000,  0x00FF, .read_8 = z80_vdp_port_read, .write_8 = z80_vdp_port_write}
 	};
 
 	char *m68k_divider = tern_find_path(config, "clocks\0m68k_divider\0", TVAL_PTR).ptrval;
@@ -1926,17 +1926,13 @@
 }
 
 static memmap_chunk base_map[] = {
-	{0xE00000, 0x1000000, 0xFFFF,   0, 0, MMAP_READ | MMAP_WRITE | MMAP_CODE, NULL,
-			   NULL,          NULL,         NULL,            NULL},
-	{0xC00000, 0xE00000,  0x1FFFFF, 0, 0, 0,                                  NULL,
-			   (read_16_fun)vdp_port_read,  (write_16_fun)vdp_port_write,
-			   (read_8_fun)vdp_port_read_b, (write_8_fun)vdp_port_write_b},
-	{0xA00000, 0xA12000,  0x1FFFF,  0, 0, 0,                                  NULL,
-			   (read_16_fun)io_read_w,      (write_16_fun)io_write_w,
-			   (read_8_fun)io_read,         (write_8_fun)io_write},
-	{0x000000, 0xFFFFFF, 0xFFFFFF, 0, 0, 0,                                   NULL,
-			   (read_16_fun)unused_read,    (write_16_fun)unused_write,
-			   (read_8_fun)unused_read_b,   (write_8_fun)unused_write_b}
+	{0xE00000, 0x1000000, 0xFFFF, .flags = MMAP_READ | MMAP_WRITE | MMAP_CODE},
+	{0xC00000, 0xE00000,  0x1FFFFF, .read_16 = (read_16_fun)vdp_port_read,  .write_16 =(write_16_fun)vdp_port_write,
+			   .read_8 = (read_8_fun)vdp_port_read_b, .write_8 = (write_8_fun)vdp_port_write_b},
+	{0xA00000, 0xA12000,  0x1FFFF,  .read_16 = (read_16_fun)io_read_w, .write_16 = (write_16_fun)io_write_w,
+			   .read_8 = (read_8_fun)io_read, .write_8 = (write_8_fun)io_write},
+	{0x000000, 0xFFFFFF, 0xFFFFFF, .read_16 = (read_16_fun)unused_read, .write_16 = unused_write,
+			   .read_8 = (read_8_fun)unused_read_b, .write_8 = (write_8_fun)unused_write_b}
 };
 const size_t base_chunks = sizeof(base_map)/sizeof(*base_map);
 
--- a/memmap.h	Thu Mar 17 22:41:42 2022 -0700
+++ b/memmap.h	Fri Mar 18 20:49:07 2022 -0700
@@ -29,6 +29,7 @@
 	uint32_t     end;
 	uint32_t     mask;
 	uint32_t     aux_mask;
+	int32_t      shift;
 	uint16_t     ptr_index;
 	uint16_t     flags;
 	void *       buffer;
--- a/segacd.c	Thu Mar 17 22:41:42 2022 -0700
+++ b/segacd.c	Fri Mar 18 20:49:07 2022 -0700
@@ -131,12 +131,11 @@
 static uint16_t word_ram_2M_read16(uint32_t address, void *vcontext)
 {
 	m68k_context *m68k = vcontext;
-	//TODO: fixme for interleaving
 	uint16_t* bank = m68k->mem_pointers[1];
 	if (!bank) {
 		return 0xFFFF;
 	}
-	uint16_t raw = bank[address >> 2];
+	uint16_t raw = bank[address >> 1 & ~1];
 	if (address & 2) {
 		return (raw & 0xF) | (raw << 4 & 0xF00);
 	} else {
@@ -157,30 +156,45 @@
 {
 	m68k_context *m68k = vcontext;
 	segacd_context *cd = m68k->system;
-	value &= 0xF;
-	uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY;
+	if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) {
+		if (address & 1) {
+			address >>= 1;
+			cd->word_ram[address] &= 0xFF00;
+			cd->word_ram[address] |= value;
+		} else {
+		address >>= 1;
+			cd->word_ram[address] &= 0x00FF;
+			cd->word_ram[address] |= value << 8;
+		}
+		cd->sub_paused_wordram = 1;
+		m68k->sync_cycle = m68k->target_cycle = m68k->current_cycle;
+		m68k->should_return = 1;
+	} else {
+		value &= 0xF;
+		uint16_t priority = cd->gate_array[GA_MEM_MODE] & MASK_PRIORITY;
 
-	if (priority == BIT_OVERWRITE && !value) {
-		return vcontext;
-	}
-	if (priority == BIT_UNDERWRITE) {
-		if (!value) {
+		if (priority == BIT_OVERWRITE && !value) {
 			return vcontext;
 		}
-		uint8_t old = word_ram_2M_read8(address, vcontext);
-		if (old) {
+		if (priority == BIT_UNDERWRITE) {
+			if (!value) {
+				return vcontext;
+			}
+			uint8_t old = word_ram_2M_read8(address, vcontext);
+			if (old) {
+				return vcontext;
+			}
+		}
+		uint16_t* bank = m68k->mem_pointers[1];
+		if (!bank) {
 			return vcontext;
 		}
-	}
-	uint16_t* bank = m68k->mem_pointers[1];
-	if (!bank) {
-		return vcontext;
+		uint16_t raw = bank[address >> 1 & ~1];
+		uint16_t shift = ((address & 3) * 4);
+		raw &= ~(0xF000 >> shift);
+		raw |= value << (12 - shift);
+		bank[address >> 1 & ~1] = raw;
 	}
-	uint16_t raw = bank[address >> 2];
-	uint16_t shift = ((address & 3) * 4);
-	raw &= ~(0xF000 >> shift);
-	raw |= value << (12 - shift);
-	bank[address >> 2] = raw;
 	return vcontext;
 }
 
@@ -234,21 +248,60 @@
 
 static uint16_t unmapped_word_read16(uint32_t address, void *vcontext)
 {
-	return 0xFFFF;
+	m68k_context *m68k = vcontext;
+	genesis_context *gen = m68k->system;
+	segacd_context *cd = gen->expansion;
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
+		return cd->word_ram[address + cd->bank_toggle];
+	} else {
+		return 0xFFFF;
+	}
 }
 
 static uint8_t unmapped_word_read8(uint32_t address, void *vcontext)
 {
-	return 0xFF;
+	m68k_context *m68k = vcontext;
+	genesis_context *gen = m68k->system;
+	segacd_context *cd = gen->expansion;
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
+		if (address & 1) {
+			return cd->word_ram[(address & ~1) + cd->bank_toggle];
+		} else {
+			return cd->word_ram[address + cd->bank_toggle] >> 8;
+		}
+	} else {
+		return 0xFF;
+	}
 }
 
 static void *unmapped_word_write16(uint32_t address, void *vcontext, uint16_t value)
 {
+	m68k_context *m68k = vcontext;
+	genesis_context *gen = m68k->system;
+	segacd_context *cd = gen->expansion;
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
+		cd->word_ram[address + cd->bank_toggle] = value;
+		m68k_invalidate_code_range(m68k, cd->base + address, address + 1);
+	}
 	return vcontext;
 }
 
 static void *unmapped_word_write8(uint32_t address, void *vcontext, uint8_t value)
 {
+	m68k_context *m68k = vcontext;
+	genesis_context *gen = m68k->system;
+	segacd_context *cd = gen->expansion;
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
+		if (address & 1) {
+			uint32_t offset = (address & ~1) + cd->bank_toggle;
+			cd->word_ram[offset] &= 0xFF00;
+			cd->word_ram[offset] |= value;
+		} else {
+			cd->word_ram[address + cd->bank_toggle] &= 0xFF;
+			cd->word_ram[address + cd->bank_toggle] |= value << 8;
+		}
+		m68k_invalidate_code_range(m68k, cd->base + (address & ~1), address + 1);
+	}
 	return vcontext;
 }
 
@@ -286,10 +339,10 @@
 	m68k_context *m68k = vcontext;
 	genesis_context *gen = m68k->system;
 	segacd_context *cd = gen->expansion;
-	if (!m68k->mem_pointers[cd->memptr_start_index + 1]) {
+	if (!(cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE)) {
 		return 0xFFFF;
 	}
-	return m68k->mem_pointers[cd->memptr_start_index + 1][address>>1];
+	return cd->word_ram[address + cd->bank_toggle];
 }
 
 static uint8_t cell_image_read8(uint32_t address, void *vcontext)
@@ -303,12 +356,12 @@
 
 static void *cell_image_write16(uint32_t address, void *vcontext, uint16_t value)
 {
-	address = cell_image_translate_address(address);
 	m68k_context *m68k = vcontext;
 	genesis_context *gen = m68k->system;
 	segacd_context *cd = gen->expansion;
-	if (m68k->mem_pointers[cd->memptr_start_index + 1]) {
-		m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] = value;
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
+		address = cell_image_translate_address(address);
+		cd->word_ram[address + cd->bank_toggle] = value;
 	}
 	return vcontext;
 }
@@ -320,13 +373,13 @@
 	m68k_context *m68k = vcontext;
 	genesis_context *gen = m68k->system;
 	segacd_context *cd = gen->expansion;
-	if (m68k->mem_pointers[cd->memptr_start_index + 1]) {
+	if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
 		if (byte) {
-			m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0xFF00;
-			m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value;
+			cd->word_ram[address + cd->bank_toggle] &= 0xFF00;
+			cd->word_ram[address + cd->bank_toggle] |= value;
 		} else {
-			m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] &= 0x00FF;
-			m68k->mem_pointers[cd->memptr_start_index + 1][address>>1] |= value << 8;
+			cd->word_ram[address + cd->bank_toggle] &= 0x00FF;
+			cd->word_ram[address + cd->bank_toggle] |= value << 8;
 		}
 	}
 	return vcontext;
@@ -624,14 +677,13 @@
 		genesis_context *gen = cd->genesis;
 		cd->gate_array[reg] &= 0xFFC0;
 		if (changed & BIT_MEM_MODE) {
-			//FIXME: ram banks are supposed to be interleaved when in 2M mode
 			cd->main_swap_request = cd->bank_toggle && !old_bank_toggle;
 			if (value & BIT_MEM_MODE) {
 				//switch to 1M mode
-				gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
+				gen->m68k->mem_pointers[cd->memptr_start_index + 1] = NULL; //(value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
 				gen->m68k->mem_pointers[cd->memptr_start_index + 2] = NULL;
 				m68k->mem_pointers[0] = NULL;
-				m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 0x10000;
+				m68k->mem_pointers[1] = cd->bank_toggle ? cd->word_ram : cd->word_ram + 1;
 				cd->gate_array[reg] |= value & (MASK_PRIORITY|BIT_RET|BIT_MEM_MODE);
 				if (cd->main_swap_request) {
 					cd->gate_array[reg] |= BIT_DMNA;
@@ -659,8 +711,7 @@
 		} else if (value & BIT_MEM_MODE) {
 			//1M mode
 			if (old_bank_toggle != cd->bank_toggle) {
-				gen->m68k->mem_pointers[cd->memptr_start_index + 1] = (value & BIT_RET) ? cd->word_ram + 0x10000 : cd->word_ram;
-				m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 0x10000;
+				m68k->mem_pointers[1] = (value & BIT_RET) ? cd->word_ram : cd->word_ram + 1;
 				m68k_invalidate_code_range(gen->m68k, cd->base + 0x200000, cd->base + 0x240000);
 				m68k_invalidate_code_range(m68k, 0x080000, 0x0E0000);
 				cd->main_swap_request = 0;
@@ -920,8 +971,8 @@
 	case DST_WORD_RAM:
 		if (cd->gate_array[GA_MEM_MODE] & BIT_MEM_MODE) {
 			//1M mode, write to bank assigned to Sub CPU
-			dma_addr &= (1 << 17) - 1;
-			cd->m68k->mem_pointers[1][dma_addr >> 1] = cd->gate_array[GA_CDC_HOST_DATA];
+			dma_addr &= (1 << 17) - 2;
+			cd->m68k->mem_pointers[1][dma_addr] = cd->gate_array[GA_CDC_HOST_DATA];
 			m68k_invalidate_code_range(cd->m68k, 0x0C0000 + dma_addr - 1, 0x0C0000 + dma_addr + 1);
 		} else {
 			//2M mode, check if Sub CPU has access
@@ -1001,7 +1052,7 @@
 {
 	uint8_t m68k_run = !can_main_access_prog(cd);
 	while (cycle > cd->m68k->current_cycle) {
-		if (m68k_run) {
+		if (m68k_run && !cd->sub_paused_wordram) {
 			uint32_t start = cd->m68k->current_cycle;
 			cd->m68k->sync_cycle = cd->enter_debugger ? cd->m68k->current_cycle + 1 : cycle;
 			if (cd->need_reset) {
@@ -1202,6 +1253,9 @@
 				cd->m68k->mem_pointers[0] = cd->word_ram;
 				cd->gate_array[reg] &= ~BIT_RET;
 				cd->main_has_word2m = 0;
+				if (cd->sub_paused_wordram) {
+					cd->sub_paused_wordram = 0;
+				}
 
 				uint16_t dst = cd->gate_array[GA_CDC_CTRL] >> 8 & 0x7;
 				if (dst == DST_WORD_RAM) {
@@ -1289,7 +1343,7 @@
 		{0x080000, 0x0C0000, 0x03FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 0,
 			.read_16 = word_ram_2M_read16, .write_16 = word_ram_2M_write16, .read_8 = word_ram_2M_read8, .write_8 = word_ram_2M_write8},
 		{0x0C0000, 0x0E0000, 0x01FFFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_CODE | MMAP_PTR_IDX | MMAP_FUNC_NULL, .ptr_index = 1,
-			.read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8},
+			.read_16 = word_ram_1M_read16, .write_16 = word_ram_1M_write16, .read_8 = word_ram_1M_read8, .write_8 = word_ram_1M_write8, .shift = 1},
 		{0xFE0000, 0xFF0000, 0x003FFF, .flags=MMAP_READ | MMAP_WRITE | MMAP_ONLY_ODD},
 		{0xFF0000, 0xFF8000, 0x003FFF, .read_16 = pcm_read16, .write_16 = pcm_write16, .read_8 = pcm_read8, .write_8 = pcm_write8},
 		{0xFF8000, 0xFF8200, 0x0001FF, .read_16 = sub_gate_read16, .write_16 = sub_gate_write16, .read_8 = sub_gate_read8, .write_8 = sub_gate_write8}
--- a/segacd.h	Thu Mar 17 22:41:42 2022 -0700
+++ b/segacd.h	Fri Mar 18 20:49:07 2022 -0700
@@ -47,6 +47,7 @@
 	uint8_t         main_has_word2m;
 	uint8_t         main_swap_request;
 	uint8_t         bank_toggle;
+	uint8_t         sub_paused_wordram;
 } segacd_context;
 
 segacd_context *alloc_configure_segacd(system_media *media, uint32_t opts, uint8_t force_region, rom_info *info);
--- a/sms.c	Thu Mar 17 22:41:42 2022 -0700
+++ b/sms.c	Fri Mar 18 20:49:07 2022 -0700
@@ -196,10 +196,10 @@
 }
 
 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},
-	{0x80, 0xC0, 0xFF, 0, 0, 0, NULL, NULL, NULL, vdp_read, vdp_write},
-	{0xC0, 0x100,0xFF, 0, 0, 0, NULL, NULL, NULL, io_read,  NULL}
+	{0x00, 0x40, 0xFF, .write_8 = memory_io_write},
+	{0x40, 0x80, 0xFF, .read_8 = hv_read, .write_8 = sms_psg_write},
+	{0x80, 0xC0, 0xFF, .read_8 = vdp_read, .write_8 = vdp_write},
+	{0xC0, 0x100,0xFF, .read_8 = io_read}
 };
 
 static void set_speed_percent(system_header * system, uint32_t percent)
@@ -216,33 +216,33 @@
 	start_section(buf, SECTION_Z80);
 	z80_serialize(sms->z80, buf);
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_VDP);
 	vdp_serialize(sms->vdp, buf);
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_PSG);
 	psg_serialize(sms->psg, buf);
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_SEGA_IO_1);
 	io_serialize(sms->io.ports, buf);
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_SEGA_IO_2);
 	io_serialize(sms->io.ports + 1, buf);
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_MAIN_RAM);
 	save_int8(buf, sizeof(sms->ram) / 1024);
 	save_buffer8(buf, sms->ram, sizeof(sms->ram));
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_MAPPER);
 	save_int8(buf, 1);//mapper type, 1 for Sega mapper
 	save_buffer8(buf, sms->bank_regs, sizeof(sms->bank_regs));
 	end_section(buf);
-	
+
 	start_section(buf, SECTION_CART_RAM);
 	save_int8(buf, SMS_CART_RAM_SIZE / 1024);
 	save_buffer8(buf, sms->cart_ram, SMS_CART_RAM_SIZE);
@@ -364,7 +364,7 @@
 			system->delayed_load_slot = slot + 1;
 		}
 		goto done;
-		
+
 	}
 #endif
 	ret = load_state_path(sms, statepath);
@@ -384,7 +384,7 @@
 		if (system->delayed_load_slot) {
 			load_state(system, system->delayed_load_slot - 1);
 			system->delayed_load_slot = 0;
-			
+
 		}
 		if (system->enter_debugger && sms->z80->pc) {
 			system->enter_debugger = 0;
@@ -407,7 +407,7 @@
 		target_cycle = sms->z80->Z80_CYCLE;
 		vdp_run_context(sms->vdp, target_cycle);
 		psg_run(sms->psg, target_cycle);
-		
+
 		if (system->save_state) {
 			while (!sms->z80->pc) {
 				//advance Z80 to an instruction boundary
@@ -416,7 +416,7 @@
 			save_state(sms, system->save_state - 1);
 			system->save_state = 0;
 		}
-		
+
 		target_cycle += 3420*16;
 		if (target_cycle > 0x10000000) {
 			uint32_t adjust = sms->z80->Z80_CYCLE - 3420*262*2;
@@ -451,19 +451,19 @@
 static void start_sms(system_header *system, char *statefile)
 {
 	sms_context *sms = (sms_context *)system;
-	
+
 	z80_assert_reset(sms->z80, 0);
 	z80_clear_reset(sms->z80, 128*15);
-	
+
 	if (statefile) {
 		load_state_path(sms, statefile);
 	}
-	
+
 	if (system->enter_debugger) {
 		system->enter_debugger = 0;
 		zinsert_breakpoint(sms->z80, sms->z80->pc, (uint8_t *)zdebugger);
 	}
-	
+
 	run_sms(system);
 }
 
@@ -592,16 +592,16 @@
 	if (media->size > 0xC000)  {
 		sms->header.info.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,                        media->buffer, NULL, NULL, NULL, NULL};
-		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF,             0, 0, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
-		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF,             0, 1, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, NULL};
-		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF,             0, 2, MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, NULL,     NULL, NULL, NULL, cart_ram_write};
-		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, 0x0003,             0, 0, MMAP_READ,                        ram_reg_overlap, NULL, NULL, NULL, mapper_write};
+		memory_map[0] = (memmap_chunk){0x0000, 0x0400,  0xFFFF, .flags = MMAP_READ, .buffer = media->buffer};
+		memory_map[1] = (memmap_chunk){0x0400, 0x4000,  0xFFFF, .ptr_index = 0, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE};
+		memory_map[2] = (memmap_chunk){0x4000, 0x8000,  0x3FFF, .ptr_index = 1, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE};
+		memory_map[3] = (memmap_chunk){0x8000, 0xC000,  0x3FFF, .ptr_index = 2, .flags = MMAP_READ|MMAP_PTR_IDX|MMAP_CODE, .write_8 = cart_ram_write};
+		memory_map[4] = (memmap_chunk){0xC000, 0xFFFC,  sizeof(sms->ram)-1, .ptr_index = 0, .flags = MMAP_READ|MMAP_WRITE|MMAP_CODE, .buffer = sms->ram};
+		memory_map[5] = (memmap_chunk){0xFFFC, 0x10000, 0x0003, .ptr_index = 0, .flags = MMAP_READ, .buffer = ram_reg_overlap, .write_8 = mapper_write};
 	} else {
 		sms->header.info.map_chunks = 2;
-		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, MMAP_READ,                      media->buffer,  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};
+		memory_map[0] = (memmap_chunk){0x0000, 0xC000,  rom_size-1,         0, 0, .flags = MMAP_READ, .buffer = media->buffer};
+		memory_map[1] = (memmap_chunk){0xC000, 0x10000, sizeof(sms->ram)-1, 0, 0, .flags = MMAP_READ|MMAP_WRITE|MMAP_CODE, .buffer = sms->ram};
 	};
 	sms->header.info.map = malloc(sizeof(memmap_chunk) * sms->header.info.map_chunks);
 	memcpy(sms->header.info.map, memory_map, sizeof(memmap_chunk) * sms->header.info.map_chunks);
@@ -610,7 +610,7 @@
 	sms->z80 = init_z80_context(zopts);
 	sms->z80->system = sms;
 	sms->z80->Z80_OPTS->gen.debug_cmd_handler = debug_commands;
-	
+
 	sms->rom = media->buffer;
 	sms->rom_size = rom_size;
 	if (sms->header.info.map_chunks > 2) {
@@ -621,24 +621,24 @@
 		sms->bank_regs[2] = 0x4000 >> 14;
 		sms->bank_regs[3] = 0x8000 >> 14;
 	}
-	
+
 	//TODO: Detect region and pick master clock based off of that
 	sms->normal_clock = sms->master_clock = 53693175;
-	
+
 	sms->psg = malloc(sizeof(psg_context));
 	psg_init(sms->psg, sms->master_clock, 15*16);
-	
+
 	set_gain_config(sms);
-	
+
 	sms->vdp = init_vdp_context(0, 0);
 	sms->vdp->system = &sms->header;
-	
+
 	sms->header.info.save_type = SAVE_NONE;
 	sms->header.info.name = strdup(media->name);
-	
+
 	setup_io_devices(config, &sms->header.info, &sms->io);
 	sms->header.has_keyboard = io_has_keyboard(&sms->io);
-	
+
 	sms->header.set_speed_percent = set_speed_percent;
 	sms->header.start_context = start_sms;
 	sms->header.resume_context = resume_sms;
@@ -662,6 +662,6 @@
 	sms->header.serialize = serialize;
 	sms->header.deserialize = deserialize;
 	sms->header.type = SYSTEM_SMS;
-	
+
 	return sms;
-}
\ No newline at end of file
+}