# HG changeset patch # User Michael Pavone # Date 1516035883 28800 # Node ID 8f3b6a64b658fafebed1eaca46f33742cb55a577 # Parent 2e6320d261ffad163640d9f0b46124eb074cf99f Initial work on MegaWiFi support diff -r 2e6320d261ff -r 8f3b6a64b658 Makefile --- 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 diff -r 2e6320d261ff -r 8f3b6a64b658 megawifi.c --- /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 +#include +#include +#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); +} diff -r 2e6320d261ff -r 8f3b6a64b658 megawifi.h --- /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_ diff -r 2e6320d261ff -r 8f3b6a64b658 mw_commands.c --- /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 diff -r 2e6320d261ff -r 8f3b6a64b658 rom.db --- 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 + } + } +} diff -r 2e6320d261ff -r 8f3b6a64b658 romdb.c --- 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); }