changeset 1519:1f745318f10a

Made the NOR flash emulation a bit more flexible, but not yet flexible enough to properly support the flash chip in the MegaWiFi cart
author Michael Pavone <pavone@retrodev.com>
date Wed, 31 Jan 2018 22:05:10 -0800
parents 713b504dc577
children f7fe240a7da6
files backend.c backend.h genesis.c nor.c rom.db romdb.c romdb.h
diffstat 7 files changed, 70 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/backend.c	Wed Jan 31 21:59:08 2018 -0800
+++ b/backend.c	Wed Jan 31 22:05:10 2018 -0800
@@ -75,7 +75,7 @@
 	for (uint32_t chunk = 0; chunk < opts->memmap_chunks; chunk++)
 	{
 		if (address >= memmap[chunk].start && address < memmap[chunk].end) {
-			if (!(memmap[chunk].flags & MMAP_READ)) {
+			if (!(memmap[chunk].flags & (MMAP_READ|MMAP_READ_CODE))) {
 				return NULL;
 			}
 			uint8_t * base = memmap[chunk].flags & MMAP_PTR_IDX
--- a/backend.h	Wed Jan 31 21:59:08 2018 -0800
+++ b/backend.h	Wed Jan 31 22:05:10 2018 -0800
@@ -56,6 +56,7 @@
 #define MMAP_FUNC_NULL 0x40
 #define MMAP_BYTESWAP  0x80
 #define MMAP_AUX_BUFF  0x100
+#define MMAP_READ_CODE 0x200
 
 typedef uint16_t (*read_16_fun)(uint32_t address, void * context);
 typedef uint8_t (*read_8_fun)(uint32_t address, void * context);
--- a/genesis.c	Wed Jan 31 21:59:08 2018 -0800
+++ b/genesis.c	Wed Jan 31 22:05:10 2018 -0800
@@ -1288,7 +1288,8 @@
 		if (gen->save_type == SAVE_I2C) {
 			eeprom_init(&gen->eeprom, gen->save_storage, gen->save_size);
 		} else if (gen->save_type == SAVE_NOR) {
-			nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus);
+			memcpy(&gen->nor, rom->nor, sizeof(gen->nor));
+			//nor_flash_init(&gen->nor, gen->save_storage, gen->save_size, rom->save_page_size, rom->save_product_id, rom->save_bus);
 		}
 	} else {
 		gen->save_storage = NULL;
--- a/nor.c	Wed Jan 31 21:59:08 2018 -0800
+++ b/nor.c	Wed Jan 31 22:05:10 2018 -0800
@@ -1,6 +1,7 @@
 #include "genesis.h"
 #include <stdlib.h>
 #include <string.h>
+#include "util.h"
 
 enum {
 	NOR_NORMAL,
@@ -31,9 +32,11 @@
 	state->cmd_state = NOR_CMD_IDLE;
 	state->alt_cmd = 0;
 	state->bus_flags = bus_flags;
+	state->cmd_address1 = 0x5555;
+	state->cmd_address2 = 0x2AAA;
 }
 
-void nor_run(nor_state *state, uint32_t cycle)
+void nor_run(nor_state *state, m68k_context *m68k, uint32_t cycle)
 {
 	if (state->last_write_cycle == 0xFFFFFFFF) {
 		return;
@@ -44,6 +47,10 @@
 			state->buffer[state->current_page + i] = state->page_buffer[i];
 		}
 		memset(state->page_buffer, 0xFF, state->page_size);
+		if (state->bus_flags == RAM_FLAG_BOTH) {
+			//TODO: add base address of NOR device to start and end addresses
+			m68k_invalidate_code_range(m68k, state->current_page, state->current_page + state->page_size);
+		}
 	}
 }
 
@@ -62,10 +69,13 @@
 		address = address >> 1;
 	}
 	
-	nor_run(state, m68k->current_cycle);
+	nor_run(state, m68k, m68k->current_cycle);
 	switch (state->mode)
 	{
 	case NOR_NORMAL:
+		if (state->bus_flags == RAM_FLAG_BOTH) {
+			address ^= 1;
+		}
 		return state->buffer[address & (state->size-1)];
 		break;
 	case NOR_PRODUCTID:
@@ -80,7 +90,7 @@
 			return 0xFE;
 		default:
 			return 0xFE;
-		}
+		}			//HERE
 		break;
 	case NOR_BOOTBLOCK:
 		break;
@@ -103,6 +113,9 @@
 		if (state->last_write_cycle != 0xFFFFFFFF) {
 			state->current_page = address & (state->size - 1) & ~(state->page_size - 1);
 		}
+		if (state->bus_flags == RAM_FLAG_BOTH) {
+			address ^= 1;
+		}
 		state->page_buffer[address & (state->page_size - 1)] = value;
 		break;
 	case NOR_PRODUCTID:
@@ -129,11 +142,11 @@
 		address = address >> 1;
 	}
 	
-	nor_run(state, m68k->current_cycle);
+	nor_run(state, m68k, m68k->current_cycle);
 	switch (state->cmd_state)
 	{
 	case NOR_CMD_IDLE:
-		if (value == 0xAA && (address & (state->size - 1)) == 0x5555) {
+		if (value == 0xAA && (address & (state->size - 1)) == state->cmd_address1) {
 			state->cmd_state = NOR_CMD_AA;
 		} else {
 			nor_write_byte(state, address, value, m68k->current_cycle);
@@ -141,16 +154,16 @@
 		}
 		break;
 	case NOR_CMD_AA:
-		if (value == 0x55 && (address & (state->size - 1)) == 0x2AAA) {
+		if (value == 0x55 && (address & (state->size - 1)) == state->cmd_address2) {
 			state->cmd_state = NOR_CMD_55;
 		} else {
-			nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
+			nor_write_byte(state, state->cmd_address1, 0xAA, m68k->current_cycle);
 			nor_write_byte(state, address, value, m68k->current_cycle);
 			state->cmd_state = NOR_CMD_IDLE;
 		}
 		break;
 	case NOR_CMD_55:
-		if ((address & (state->size - 1)) == 0x5555) {
+		if ((address & (state->size - 1)) == state->cmd_address1) {
 			if (state->alt_cmd) {
 				switch(value)
 				{
@@ -187,8 +200,8 @@
 				}
 			}
 		} else {
-			nor_write_byte(state, 0x5555, 0xAA, m68k->current_cycle);
-			nor_write_byte(state, 0x2AAA, 0x55, m68k->current_cycle);
+			nor_write_byte(state, state->cmd_address1, 0xAA, m68k->current_cycle);
+			nor_write_byte(state, state->cmd_address2, 0x55, m68k->current_cycle);
 			nor_write_byte(state, address, value, m68k->current_cycle);
 		}
 		state->cmd_state = NOR_CMD_IDLE;
--- a/rom.db	Wed Jan 31 21:59:08 2018 -0800
+++ b/rom.db	Wed Jan 31 22:05:10 2018 -0800
@@ -1301,9 +1301,18 @@
 }
 cda73e4caf53cbc8f0750b69e5e7f394ad3735d1 {
 	name MegaWiFi Bootloader
+	NOR {
+		size 4194304
+		page_size 128
+		product_id DA45
+		bus both
+		init ROM
+		cmd_address1 AAB
+		cmd_address2 555
+	}
 	map {
 		0 {
-			device ROM
+			device NOR
 			last 3FFFFF
 		}
 		A130C0 {
--- a/romdb.c	Wed Jan 31 21:59:08 2018 -0800
+++ b/romdb.c	Wed Jan 31 22:05:10 2018 -0800
@@ -57,6 +57,7 @@
 	free(info->port2_override);
 	free(info->ext_override);
 	free(info->mouse_mode);
+	free(info->nor);
 }
 
 void cart_serialize(system_header *sys, serialize_buffer *buf)
@@ -500,15 +501,15 @@
 		if (!page_size) {
 			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR page size is not defined\n", state->index, key);
 		}
-		state->info->save_page_size = atoi(size);
-		if (!state->info->save_page_size) {
-			fatal_error("NOR page size %s is invalid\n", size);
+		uint32_t save_page_size = atoi(page_size);
+		if (!save_page_size) {
+			fatal_error("NOR page size %s is invalid\n", page_size);
 		}
 		char *product_id = tern_find_path(state->root, "NOR\0product_id\0", TVAL_PTR).ptrval;
 		if (!product_id) {
 			fatal_error("ROM DB map entry %d with address %s has device type NOR, but the NOR product ID is not defined\n", state->index, key);
 		}
-		state->info->save_product_id = strtol(product_id, NULL, 16);
+		uint16_t save_product_id = strtol(product_id, NULL, 16);
 		char *bus = tern_find_path(state->root, "NOR\0bus\0", TVAL_PTR).ptrval;
 		if (!strcmp(bus, "odd")) {
 			state->info->save_bus = RAM_FLAG_ODD;
@@ -519,7 +520,26 @@
 		}
 		state->info->save_type = SAVE_NOR;
 		state->info->save_buffer = malloc(state->info->save_size);
-		memset(state->info->save_buffer, 0xFF, state->info->save_size);
+		char *init = tern_find_path_default(state->root, "NOR\0init\0", (tern_val){.ptrval="FF"}, TVAL_PTR).ptrval;
+		if (!strcmp(init, "ROM")) {
+			uint32_t init_size = state->rom_size > state->info->save_size ? state->info->save_size : state->rom_size;
+			memcpy(state->info->save_buffer, state->rom, init_size);
+			if (state->info->save_bus == RAM_FLAG_BOTH) {
+				byteswap_rom(state->info->save_size, (uint16_t *)state->info->save_buffer);
+			}
+		} else {
+			memset(state->info->save_buffer, strtol(init, NULL, 16), state->info->save_size);
+		}
+		state->info->nor = calloc(1, sizeof(nor_state));
+		nor_flash_init(state->info->nor, state->info->save_buffer, state->info->save_size, save_page_size, save_product_id, state->info->save_bus);
+		char *cmd1 = tern_find_path(state->root, "NOR\0cmd_address1\0", TVAL_PTR).ptrval;
+		if (cmd1) {
+			state->info->nor->cmd_address1 = strtol(cmd1, NULL, 16);
+		}
+		char *cmd2 = tern_find_path(state->root, "NOR\0cmd_address2\0", TVAL_PTR).ptrval;
+		if (cmd2) {
+			state->info->nor->cmd_address2 = strtol(cmd2, NULL, 16);
+		}
 	}
 }
 
@@ -616,8 +636,7 @@
 			state->info->save_buffer = lock_info.save_buffer;
 			state->info->save_size = lock_info.save_size;
 			state->info->save_mask = lock_info.save_mask;
-			state->info->save_page_size = lock_info.save_page_size;
-			state->info->save_product_id = lock_info.save_product_id;
+			state->info->nor = lock_info.nor;
 			state->info->save_type = lock_info.save_type;
 			state->info->save_bus = lock_info.save_bus;
 			lock_info.save_buffer = NULL;
@@ -667,6 +686,10 @@
 		map->write_8 = nor_flash_write_b;
 		map->read_16 = nor_flash_read_w;
 		map->read_8 = nor_flash_read_b;
+		if (state->info->save_bus == RAM_FLAG_BOTH) {
+			map->flags |= MMAP_READ_CODE | MMAP_CODE;
+			map->buffer = state->info->save_buffer;
+		}
 		map->mask = 0xFFFFFF;
 	} else if (!strcmp(dtype, "Sega mapper")) {
 		state->info->mapper_type = MAPPER_SEGA;
--- a/romdb.h	Wed Jan 31 21:59:08 2018 -0800
+++ b/romdb.h	Wed Jan 31 22:05:10 2018 -0800
@@ -31,6 +31,8 @@
 	uint32_t    page_size;
 	uint32_t    current_page;
 	uint32_t    last_write_cycle;
+	uint32_t    cmd_address1;
+	uint32_t    cmd_address2;
 	uint16_t    product_id;
 	uint8_t     mode;
 	uint8_t     cmd_state;
@@ -61,13 +63,12 @@
 	char          *port2_override;
 	char          *ext_override;
 	char          *mouse_mode;
+	nor_state     *nor;
 	uint32_t      num_eeprom;
 	uint32_t      map_chunks;
 	uint32_t      rom_size;
 	uint32_t      save_size;
 	uint32_t      save_mask;
-	uint32_t      save_page_size;
-	uint16_t      save_product_id;
 	uint16_t      mapper_start_index;
 	uint8_t       save_type;
 	uint8_t       save_bus; //only used for NOR currently