changeset 1513:8f3b6a64b658

Initial work on MegaWiFi support
author Michael Pavone <pavone@retrodev.com>
date Mon, 15 Jan 2018 09:04:43 -0800
parents 2e6320d261ff
children 4f94e0f90c83
files Makefile megawifi.c megawifi.h mw_commands.c rom.db romdb.c
diffstat 6 files changed, 301 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Thu Oct 19 03:21:24 2017 -0700
+++ b/Makefile	Mon Jan 15 09:04:43 2018 -0800
@@ -127,7 +127,7 @@
 AUDIOOBJS=ym2612.o psg.o wave.o
 CONFIGOBJS=config.o tern.o util.o
 
-MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o sega_mapper.o multi_game.o serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
+MAINOBJS=blastem.o system.o genesis.o debug.o gdb_remote.o vdp.o render_sdl.o ppm.o io.o romdb.o hash.o menu.o xband.o realtec.o i2c.o nor.o sega_mapper.o multi_game.o megawifi.o serialize.o $(TERMINAL) $(CONFIGOBJS) gst.o $(M68KOBJS) $(TRANSOBJS) $(AUDIOOBJS)
 
 ifeq ($(CPU),x86_64)
 CFLAGS+=-DX86_64 -m64
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/megawifi.c	Mon Jan 15 09:04:43 2018 -0800
@@ -0,0 +1,238 @@
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include "genesis.h"
+
+enum {
+	TX_IDLE,
+	TX_LEN1,
+	TX_LEN2,
+	TX_PAYLOAD,
+	TX_WAIT_ETX
+};
+#define STX 0x7E
+#define ETX 0x7E
+
+#define E(N) N
+enum {
+#include "mw_commands.c"
+	CMD_ERROR = 255
+};
+#undef E
+#define E(N) #N
+static const char *cmd_names[] = {
+#include "mw_commands.c"
+	[255] = "CMD_ERROR"
+};
+
+enum {
+	STATE_IDLE=1,
+	STATE_AP_JOIN,
+	STATE_SCAN,
+	STATE_READY,
+	STATE_TRANSPARENT
+};
+
+#define FLAG_ONLINE 
+
+typedef struct {
+	uint32_t transmit_bytes;
+	uint32_t expected_bytes;
+	uint32_t receive_bytes;
+	uint32_t receive_read;
+	uint16_t channel_flags;
+	uint8_t  scratchpad;
+	uint8_t  transmit_channel;
+	uint8_t  transmit_state;
+	uint8_t  module_state;
+	uint8_t  flags;
+	uint8_t  transmit_buffer[4096];
+	uint8_t  receive_buffer[4096];
+} megawifi;
+
+static megawifi *get_megawifi(void *context)
+{
+	m68k_context *m68k = context;
+	genesis_context *gen = m68k->system;
+	if (!gen->extra) {
+		gen->extra = calloc(1, sizeof(megawifi));
+		((megawifi *)gen->extra)->module_state = STATE_IDLE;
+	}
+	return gen->extra;
+}
+
+static void mw_putc(megawifi *mw, uint8_t v)
+{
+	if (mw->receive_bytes == sizeof(mw->receive_buffer)) {
+		return;
+	}
+	mw->receive_buffer[mw->receive_bytes++] = v;
+}
+
+static void mw_puts(megawifi *mw, char *s)
+{
+	uint32_t len = strlen(s);
+	if ((mw->receive_bytes + len) > sizeof(mw->receive_buffer)) {
+		return;
+	}
+	memcpy(mw->receive_buffer + mw->receive_bytes, s, len);
+	mw->receive_bytes += len;
+}
+
+static void process_packet(megawifi *mw)
+{
+	if (mw->transmit_channel == 0) {
+		uint32_t command = mw->transmit_buffer[0] << 8 | mw->transmit_buffer[1];
+		uint32_t size = mw->transmit_buffer[2] << 8 | mw->transmit_buffer[3];
+		if (size > mw->transmit_bytes - 4) {
+			size = mw->transmit_bytes - 4;
+		}
+		mw->receive_read = mw->receive_bytes = 0;
+		switch (command)
+		{
+		case CMD_VERSION:
+			//LSD header
+			mw_putc(mw, 0x7E);
+			mw_putc(mw, 0);
+			mw->receive_bytes += 1; //reserve space for LSB of len
+			//cmd
+			mw_putc(mw, 0);
+			mw_putc(mw, CMD_OK);
+			//length
+			mw_putc(mw, 0);
+			mw->receive_bytes += 1; //reserve space for LSB of len
+			mw_putc(mw, 1);
+			mw_putc(mw, 0);
+			mw_puts(mw, "blastem");
+			mw->receive_buffer[2] = mw->receive_bytes - 3;
+			mw->receive_buffer[6] = mw->receive_bytes - 7;
+			mw_putc(mw, 0x7E);
+			break;
+		case CMD_ECHO:
+			mw->receive_bytes = mw->transmit_bytes;
+			memcpy(mw->receive_buffer, mw->transmit_buffer, mw->transmit_bytes);
+			break;
+		case CMD_AP_JOIN:
+			mw->module_state = STATE_READY;
+			mw_putc(mw, 0x7E);
+			mw_putc(mw, 0);
+			mw_putc(mw, 4);
+			//cmd
+			mw_putc(mw, 0);
+			mw_putc(mw, CMD_OK);
+			//length
+			mw_putc(mw, 0);
+			mw_putc(mw, 0);
+			mw_putc(mw, 0x7E);
+			break;
+		case CMD_SYS_STAT:
+			//LSD header
+			mw_putc(mw, 0x7E);
+			mw_putc(mw, 0);
+			mw_putc(mw, 8);
+			//cmd
+			mw_putc(mw, 0);
+			mw_putc(mw, CMD_OK);
+			//length
+			mw_putc(mw, 0);
+			mw_putc(mw, 4);
+			mw_putc(mw, mw->module_state);
+			mw_putc(mw, mw->flags);
+			mw_putc(mw, mw->channel_flags >> 8);
+			mw_putc(mw, mw->channel_flags);
+			mw_putc(mw, 0x7E);
+			break;
+		default:
+			printf("Unhandled MegaWiFi command %s(%d) with length %X\n", cmd_names[command], command, size);
+			break;
+		}
+	} else {
+		printf("Unhandled receive of MegaWiFi data on channel %d\n", mw->transmit_channel);
+	}
+	mw->transmit_bytes = mw->expected_bytes = 0;
+}
+
+void *megawifi_write_b(uint32_t address, void *context, uint8_t value)
+{
+	if (!(address & 1)) {
+		return context;
+	}
+	megawifi *mw = get_megawifi(context);
+	address = address >> 1 & 7;
+	switch (address)
+	{
+	case 0:
+		switch (mw->transmit_state)
+		{
+		case TX_IDLE:
+			if (value == STX) {
+				mw->transmit_state = TX_LEN1;
+			}
+			break;
+		case TX_LEN1:
+			mw->transmit_channel = value >> 4;
+			mw->expected_bytes = value << 8 & 0xF00;
+			mw->transmit_state = TX_LEN2;
+			break;
+		case TX_LEN2:
+			mw->expected_bytes |= value;
+			mw->transmit_state = TX_PAYLOAD;
+			break;
+		case TX_PAYLOAD:
+			mw->transmit_buffer[mw->transmit_bytes++] = value;
+			if (mw->transmit_bytes == mw->expected_bytes) {
+				mw->transmit_state = TX_WAIT_ETX;
+			}
+			break;
+		case TX_WAIT_ETX:
+			if (value == ETX) {
+				mw->transmit_state = TX_IDLE;
+				process_packet(mw);
+			}
+			break;
+		}
+		break;
+	case 7:
+		mw->scratchpad = value;
+		break;
+	default:
+		printf("Unhandled write to MegaWiFi UART register %X: %X\n", address, value);
+	}
+	return context;
+}
+
+void *megawifi_write_w(uint32_t address, void *context, uint16_t value)
+{
+	return megawifi_write_b(address | 1, context, value);
+}
+
+uint8_t megawifi_read_b(uint32_t address, void *context)
+{
+	
+	if (!(address & 1)) {
+		return 0xFF;
+	}
+	megawifi *mw = get_megawifi(context);
+	address = address >> 1 & 7;
+	switch (address)
+	{
+	case 0:
+		if (mw->receive_read < mw->receive_bytes) {
+			return mw->receive_buffer[mw->receive_read++];
+		}
+		return 0xFF;
+	case 5:
+		//line status
+		return 0x60 | (mw->receive_read < mw->receive_bytes);
+	case 7:
+		return mw->scratchpad;
+	default:
+		printf("Unhandled read from MegaWiFi UART register %X\n", address);
+		return 0xFF;
+	}
+}
+
+uint16_t megawifi_read_w(uint32_t address, void *context)
+{
+	return 0xFF00 | megawifi_read_b(address | 1, context);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/megawifi.h	Mon Jan 15 09:04:43 2018 -0800
@@ -0,0 +1,9 @@
+#ifndef MEGAWIFI_H_
+#define MEGAWIFI_H_
+
+void *megawifi_write_w(uint32_t address, void *context, uint16_t value);
+void *megawifi_write_b(uint32_t address, void *context, uint8_t value);
+uint16_t megawifi_read_w(uint32_t address, void *context);
+uint8_t megawifi_read_b(uint32_t address, void *context);
+
+#endif //MEGAWIFI_H_
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mw_commands.c	Mon Jan 15 09:04:43 2018 -0800
@@ -0,0 +1,33 @@
+	E(CMD_OK),
+	E(CMD_VERSION),
+	E(CMD_ECHO),
+	E(CMD_AP_SCAN),
+	E(CMD_AP_CFG),
+	E(CMD_AP_CFG_GET),
+	E(CMD_IP_CURRENT),
+	E(CMD_RESERVED),
+	E(CMD_IP_CFG),
+	E(CMD_IP_CFG_GET),
+	E(CMD_DEF_AP_CFG),
+	E(CMD_DEF_AP_CFG_GET),
+	E(CMD_AP_JOIN),
+	E(CMD_AP_LEAVE),
+	E(CMD_TCP_CON),
+	E(CMD_TCP_BIND),
+	E(CMD_TCP_ACCEPT),
+	E(CMD_TCP_DISC),
+	E(CMD_UDP_SET),
+	E(CMD_UDP_CLR),
+	E(CMD_SOCK_STAT),
+	E(CMD_PING),
+	E(CMD_SNTP_CFG),
+	E(CMD_SNTP_CFG_GET),
+	E(CMD_DATETIME),
+	E(CMD_DT_SET),
+	E(CMD_FLASH_WRITE),
+	E(CMD_FLASH_READ),
+	E(CMD_FLASH_ERASE),
+	E(CMD_FLASH_ID),
+	E(CMD_SYS_STAT),
+	E(CMD_DEF_CFG_SET),
+	E(CMD_HRNG_GET),
\ No newline at end of file
--- a/rom.db	Thu Oct 19 03:21:24 2017 -0700
+++ b/rom.db	Mon Jan 15 09:04:43 2018 -0800
@@ -1299,3 +1299,16 @@
 		}
 	}
 }
+cda73e4caf53cbc8f0750b69e5e7f394ad3735d1 {
+	name MegaWiFi Bootloader
+	map {
+		0 {
+			device ROM
+			last 3FFFFF
+		}
+		A130C0 {
+			device megawifi
+			last A130CF
+		}
+	}
+}
--- a/romdb.c	Thu Oct 19 03:21:24 2017 -0700
+++ b/romdb.c	Mon Jan 15 09:04:43 2018 -0800
@@ -11,6 +11,7 @@
 #include "nor.h"
 #include "sega_mapper.h"
 #include "multi_game.h"
+#include "megawifi.h"
 
 #define DOM_TITLE_START 0x120
 #define DOM_TITLE_END 0x150
@@ -778,6 +779,12 @@
 		map->mask = 0xFF;
 		map->write_16 = write_multi_game_w;
 		map->write_8 = write_multi_game_b;
+	} else if (!strcmp(dtype, "megawifi")) {
+		map->write_16 = megawifi_write_w;
+		map->write_8 = megawifi_write_b;
+		map->read_16 = megawifi_read_w;
+		map->read_8 = megawifi_read_b;
+		map->mask = 0xFFFFFF;
 	} else {
 		fatal_error("Invalid device type %s for ROM DB map entry %d with address %s\n", dtype, state->index, key);
 	}