Initial work on MegaWiFi support

This commit is contained in:
Michael Pavone committed 2018-01-15 09:04:43 -08:00
1 parent 15b6f9038a
commit d85bd0c943
6 files changed
+301 -1

No files matched your search

+1 -1
View File
@@ -127,7 +127,7 @@ Z80OBJS=z80inst.o z80_to_x86.o
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
+238
View File
@@ -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);
}
+9
View File
@@ -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_
+33
View File
@@ -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),
+13
View File
@@ -1299,3 +1299,16 @@ e1c041ba69da087c428dcda16850159f3caebd4b {
}
}
}
cda73e4caf53cbc8f0750b69e5e7f394ad3735d1 {
name MegaWiFi Bootloader
map {
0 {
device ROM
last 3FFFFF
}
A130C0 {
device megawifi
last A130CF
}
}
}
+7
View File
@@ -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 @@ void map_iter_fun(char *key, tern_val val, uint8_t valtype, void *data)
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);
}