mirror of
https://github.com/libretro/blastem.git
synced 2026-11-07 10:15:58 -10:00
Initial work on MegaWiFi support
This commit is contained in:
1 parent
15b6f9038a
commit
d85bd0c943
6 files changed
+301
-1
No files matched your search
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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_
|
||||
@@ -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),
|
||||
@@ -1299,3 +1299,16 @@ e1c041ba69da087c428dcda16850159f3caebd4b {
|
||||
}
|
||||
}
|
||||
}
|
||||
cda73e4caf53cbc8f0750b69e5e7f394ad3735d1 {
|
||||
name MegaWiFi Bootloader
|
||||
map {
|
||||
0 {
|
||||
device ROM
|
||||
last 3FFFFF
|
||||
}
|
||||
A130C0 {
|
||||
device megawifi
|
||||
last A130CF
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user