convert Wifi and WifiAP

This commit is contained in:
Arisotura 2023-11-04 17:00:12 +01:00
parent 76976fef30
commit 2bd09eafeb
7 changed files with 376 additions and 367 deletions

View File

@ -1212,7 +1212,7 @@ int ClassifyAddress7(u32 addr)
} }
} }
void WifiWrite32(u32 addr, u32 val) /*void WifiWrite32(u32 addr, u32 val)
{ {
Wifi::Write(addr, val & 0xFFFF); Wifi::Write(addr, val & 0xFFFF);
Wifi::Write(addr + 2, val >> 16); Wifi::Write(addr + 2, val >> 16);
@ -1221,7 +1221,7 @@ void WifiWrite32(u32 addr, u32 val)
u32 WifiRead32(u32 addr) u32 WifiRead32(u32 addr)
{ {
return (u32)Wifi::Read(addr) | ((u32)Wifi::Read(addr + 2) << 16); return (u32)Wifi::Read(addr) | ((u32)Wifi::Read(addr + 2) << 16);
} }*/
template <typename T> template <typename T>
void VRAMWrite(u32 addr, T val) void VRAMWrite(u32 addr, T val)
@ -1358,7 +1358,8 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
} }
} }
break; break;
case 0x04800000: // TODO: the wifi funcs also ought to check POWCNT
/*case 0x04800000:
if (addr < 0x04810000 && size >= 16) if (addr < 0x04810000 && size >= 16)
{ {
switch (size | store) switch (size | store)
@ -1369,7 +1370,7 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
case 33: return (void*)WifiWrite32; case 33: return (void*)WifiWrite32;
} }
} }
break; break;*/
case 0x06000000: case 0x06000000:
case 0x06800000: case 0x06800000:
switch (size | store) switch (size | store)

View File

@ -181,6 +181,7 @@ u16 RCnt;
class SPU* SPU; class SPU* SPU;
class SPIHost* SPI; class SPIHost* SPI;
class RTC* RTC; class RTC* RTC;
class Wifi* Wifi;
bool Running; bool Running;
@ -222,11 +223,11 @@ bool Init()
SPU = new class SPU; SPU = new class SPU;
SPI = new class SPIHost(); SPI = new class SPIHost();
RTC = new class RTC(); RTC = new class RTC();
Wifi = new class Wifi();
if (!NDSCart::Init()) return false; if (!NDSCart::Init()) return false;
if (!GBACart::Init()) return false; if (!GBACart::Init()) return false;
if (!GPU::Init()) return false; if (!GPU::Init()) return false;
if (!Wifi::Init()) return false;
if (!DSi::Init()) return false; if (!DSi::Init()) return false;
@ -253,11 +254,11 @@ void DeInit()
delete SPU; SPU = nullptr; delete SPU; SPU = nullptr;
delete SPI; SPI = nullptr; delete SPI; SPI = nullptr;
delete RTC; RTC = nullptr; delete RTC; RTC = nullptr;
delete Wifi; Wifi = nullptr;
NDSCart::DeInit(); NDSCart::DeInit();
GBACart::DeInit(); GBACart::DeInit();
GPU::DeInit(); GPU::DeInit();
Wifi::DeInit();
DSi::DeInit(); DSi::DeInit();
@ -646,7 +647,7 @@ void Reset()
SPU->Reset(); SPU->Reset();
SPI->Reset(); SPI->Reset();
RTC->Reset(); RTC->Reset();
Wifi::Reset(); Wifi->Reset();
// TODO: move the SOUNDBIAS/degrade logic to SPU? // TODO: move the SOUNDBIAS/degrade logic to SPU?
@ -848,7 +849,7 @@ bool DoSavestate(Savestate* file)
SPU->DoSavestate(file); SPU->DoSavestate(file);
SPI->DoSavestate(file); SPI->DoSavestate(file);
RTC->DoSavestate(file); RTC->DoSavestate(file);
Wifi::DoSavestate(file); Wifi->DoSavestate(file);
if (ConsoleType == 1) if (ConsoleType == 1)
DSi::DoSavestate(file); DSi::DoSavestate(file);
@ -858,7 +859,7 @@ bool DoSavestate(Savestate* file)
GPU::SetPowerCnt(PowerControl9); GPU::SetPowerCnt(PowerControl9);
SPU->SetPowerCnt(PowerControl7 & 0x0001); SPU->SetPowerCnt(PowerControl7 & 0x0001);
Wifi::SetPowerCnt(PowerControl7 & 0x0002); Wifi->SetPowerCnt(PowerControl7 & 0x0002);
} }
#ifdef JIT_ENABLED #ifdef JIT_ENABLED
@ -2542,8 +2543,8 @@ u8 ARM7Read8(u32 addr)
if (addr < 0x04810000) if (addr < 0x04810000)
{ {
if (!(PowerControl7 & (1<<1))) return 0; if (!(PowerControl7 & (1<<1))) return 0;
if (addr & 0x1) return Wifi::Read(addr-1) >> 8; if (addr & 0x1) return Wifi->Read(addr-1) >> 8;
return Wifi::Read(addr) & 0xFF; return Wifi->Read(addr) & 0xFF;
} }
break; break;
@ -2609,7 +2610,7 @@ u16 ARM7Read16(u32 addr)
if (addr < 0x04810000) if (addr < 0x04810000)
{ {
if (!(PowerControl7 & (1<<1))) return 0; if (!(PowerControl7 & (1<<1))) return 0;
return Wifi::Read(addr); return Wifi->Read(addr);
} }
break; break;
@ -2675,7 +2676,7 @@ u32 ARM7Read32(u32 addr)
if (addr < 0x04810000) if (addr < 0x04810000)
{ {
if (!(PowerControl7 & (1<<1))) return 0; if (!(PowerControl7 & (1<<1))) return 0;
return Wifi::Read(addr) | (Wifi::Read(addr+2) << 16); return Wifi->Read(addr) | (Wifi->Read(addr+2) << 16);
} }
break; break;
@ -2818,7 +2819,7 @@ void ARM7Write16(u32 addr, u16 val)
if (addr < 0x04810000) if (addr < 0x04810000)
{ {
if (!(PowerControl7 & (1<<1))) return; if (!(PowerControl7 & (1<<1))) return;
Wifi::Write(addr, val); Wifi->Write(addr, val);
return; return;
} }
break; break;
@ -2898,8 +2899,8 @@ void ARM7Write32(u32 addr, u32 val)
if (addr < 0x04810000) if (addr < 0x04810000)
{ {
if (!(PowerControl7 & (1<<1))) return; if (!(PowerControl7 & (1<<1))) return;
Wifi::Write(addr, val & 0xFFFF); Wifi->Write(addr, val & 0xFFFF);
Wifi::Write(addr+2, val >> 16); Wifi->Write(addr+2, val >> 16);
return; return;
} }
break; break;
@ -4332,7 +4333,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
u16 change = PowerControl7 ^ val; u16 change = PowerControl7 ^ val;
PowerControl7 = val & 0x0003; PowerControl7 = val & 0x0003;
SPU->SetPowerCnt(val & 0x0001); SPU->SetPowerCnt(val & 0x0001);
Wifi::SetPowerCnt(val & 0x0002); Wifi->SetPowerCnt(val & 0x0002);
if (change & 0x0002) UpdateWifiTimings(); if (change & 0x0002) UpdateWifiTimings();
} }
return; return;
@ -4462,7 +4463,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
u16 change = PowerControl7 ^ val; u16 change = PowerControl7 ^ val;
PowerControl7 = val & 0x0003; PowerControl7 = val & 0x0003;
SPU->SetPowerCnt(val & 0x0001); SPU->SetPowerCnt(val & 0x0001);
Wifi::SetPowerCnt(val & 0x0002); Wifi->SetPowerCnt(val & 0x0002);
if (change & 0x0002) UpdateWifiTimings(); if (change & 0x0002) UpdateWifiTimings();
} }
return; return;

View File

@ -33,6 +33,7 @@
class SPU; class SPU;
class SPIHost; class SPIHost;
class RTC; class RTC;
class Wifi;
namespace NDS namespace NDS
{ {
@ -253,6 +254,7 @@ extern u16 RCnt;
extern class SPU* SPU; extern class SPU* SPU;
extern class SPIHost* SPI; extern class SPIHost* SPI;
extern class RTC* RTC; extern class RTC* RTC;
extern class Wifi* Wifi;
const u32 ARM7WRAMSize = 0x10000; const u32 ARM7WRAMSize = 0x10000;
extern u8* ARM7WRAM; extern u8* ARM7WRAM;

View File

@ -27,91 +27,19 @@
using Platform::Log; using Platform::Log;
using Platform::LogLevel; using Platform::LogLevel;
namespace Wifi
{
//#define WIFI_LOG printf //#define WIFI_LOG printf
#define WIFI_LOG(...) {} #define WIFI_LOG(...) {}
#define PRINT_MAC(pf, mac) Log(LogLevel::Debug, "%s: %02X:%02X:%02X:%02X:%02X:%02X\n", pf, (mac)[0], (mac)[1], (mac)[2], (mac)[3], (mac)[4], (mac)[5]); #define PRINT_MAC(pf, mac) Log(LogLevel::Debug, "%s: %02X:%02X:%02X:%02X:%02X:%02X\n", pf, (mac)[0], (mac)[1], (mac)[2], (mac)[3], (mac)[4], (mac)[5]);
u8 RAM[0x2000];
u16 IO[0x1000>>1];
#define IOPORT(x) IO[(x)>>1] #define IOPORT(x) IO[(x)>>1]
#define IOPORT8(x) ((u8*)IO)[x] #define IOPORT8(x) ((u8*)IO)[x]
// destination MACs for MP frames // destination MACs for MP frames
const u8 MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00}; const u8 Wifi::MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00};
const u8 MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10}; const u8 Wifi::MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10};
const u8 MPAckMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x03}; const u8 Wifi::MPAckMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x03};
const int kTimerInterval = 8;
const u32 kTimeCheckMask = ~(kTimerInterval - 1);
bool Enabled;
bool PowerOn;
s32 TimerError;
u16 Random;
// general, always-on microsecond counter
u64 USTimestamp;
u64 USCounter;
u64 USCompare;
bool BlockBeaconIRQ14;
u32 CmdCounter;
u8 BBRegs[0x100];
u8 BBRegsRO[0x100];
u8 RFVersion;
u32 RFRegs[0x40];
struct TXSlot
{
bool Valid;
u16 Addr;
u16 Length;
u8 Rate;
u8 CurPhase;
int CurPhaseTime;
u32 HalfwordTimeMask;
};
TXSlot TXSlots[6];
u8 TXBuffer[0x2000];
u8 RXBuffer[2048];
u32 RXBufferPtr;
int RXTime;
u32 RXHalfwordTimeMask;
u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending
u32 TXCurSlot;
u32 RXCounter;
int MPReplyTimer;
u16 MPClientMask, MPClientFail;
u8 MPClientReplies[15*1024];
u16 MPLastSeqno;
bool MPInited;
bool LANInited;
int USUntilPowerOn;
bool ForcePowerOn;
// MULTIPLAYER SYNC APPARATUS
bool IsMP;
bool IsMPClient;
u64 NextSync; // for clients: timestamp for next sync point
u64 RXTimestamp;
// multiplayer host TX sequence: // multiplayer host TX sequence:
// 1. preamble // 1. preamble
@ -148,9 +76,20 @@ u64 RXTimestamp;
// * TX errors (if applicable) // * TX errors (if applicable)
bool Init() bool MACEqual(u8* a, const u8* b)
{ {
NDS::RegisterEventFunc(NDS::Event_Wifi, 0, USTimer); return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]);
}
bool MACIsBroadcast(u8* a)
{
return (*(u32*)&a[0] == 0xFFFFFFFF) && (*(u16*)&a[4] == 0xFFFF);
}
Wifi::Wifi()
{
NDS::RegisterEventFunc(NDS::Event_Wifi, 0, MemberEventFunc(Wifi, USTimer));
//MPInited = false; //MPInited = false;
//LANInited = false; //LANInited = false;
@ -161,24 +100,22 @@ bool Init()
Platform::LAN_Init(); Platform::LAN_Init();
LANInited = true; LANInited = true;
WifiAP::Init(); WifiAP = new class WifiAP(this);
return true;
} }
void DeInit() Wifi::~Wifi()
{ {
if (MPInited) if (MPInited)
Platform::MP_DeInit(); Platform::MP_DeInit();
if (LANInited) if (LANInited)
Platform::LAN_DeInit(); Platform::LAN_DeInit();
WifiAP::DeInit(); delete WifiAP; WifiAP = nullptr;
NDS::UnregisterEventFunc(NDS::Event_Wifi, 0); NDS::UnregisterEventFunc(NDS::Event_Wifi, 0);
} }
void Reset() void Wifi::Reset()
{ {
memset(RAM, 0, 0x2000); memset(RAM, 0, 0x2000);
memset(IO, 0, 0x1000); memset(IO, 0, 0x1000);
@ -277,10 +214,10 @@ void Reset()
NextSync = 0; NextSync = 0;
RXTimestamp = 0; RXTimestamp = 0;
WifiAP::Reset(); WifiAP->Reset();
} }
void DoSavestate(Savestate* file) void Wifi::DoSavestate(Savestate* file)
{ {
file->Section("WIFI"); file->Section("WIFI");
@ -355,7 +292,7 @@ void DoSavestate(Savestate* file)
} }
void ScheduleTimer(bool first) void Wifi::ScheduleTimer(bool first)
{ {
if (first) TimerError = 0; if (first) TimerError = 0;
@ -367,7 +304,7 @@ void ScheduleTimer(bool first)
NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0); NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0);
} }
void UpdatePowerOn() void Wifi::UpdatePowerOn()
{ {
bool on = Enabled; bool on = Enabled;
@ -405,17 +342,14 @@ void UpdatePowerOn()
} }
} }
void SetPowerCnt(u32 val) void Wifi::SetPowerCnt(u32 val)
{ {
Enabled = val & (1<<1); Enabled = val & (1<<1);
UpdatePowerOn(); UpdatePowerOn();
} }
void PowerDown(); void Wifi::SetIRQ(u32 irq)
void StartTX_Beacon();
void SetIRQ(u32 irq)
{ {
u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE); u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE);
@ -426,7 +360,7 @@ void SetIRQ(u32 irq)
NDS::SetIRQ(1, NDS::IRQ_Wifi); NDS::SetIRQ(1, NDS::IRQ_Wifi);
} }
void SetIRQ13() void Wifi::SetIRQ13()
{ {
SetIRQ(13); SetIRQ(13);
@ -440,7 +374,7 @@ void SetIRQ13()
} }
} }
void SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced void Wifi::SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
{ {
if (source != 2) if (source != 2)
IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval); IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval);
@ -469,7 +403,7 @@ void SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
IOPORT(W_ListenCount)--; IOPORT(W_ListenCount)--;
} }
void SetIRQ15() void Wifi::SetIRQ15()
{ {
SetIRQ(15); SetIRQ(15);
@ -481,7 +415,7 @@ void SetIRQ15()
} }
void SetStatus(u32 status) void Wifi::SetStatus(u32 status)
{ {
// TODO, eventually: states 2/4/7 // TODO, eventually: states 2/4/7
u16 rfpins[10] = {0x04, 0x84, 0, 0x46, 0, 0x84, 0x87, 0, 0x46, 0x04}; u16 rfpins[10] = {0x04, 0x84, 0, 0x46, 0, 0x84, 0x87, 0, 0x46, 0x04};
@ -490,7 +424,7 @@ void SetStatus(u32 status)
} }
void PowerDown() void Wifi::PowerDown()
{ {
IOPORT(W_TXReqRead) &= ~0x000F; IOPORT(W_TXReqRead) &= ~0x000F;
IOPORT(W_PowerState) |= 0x0200; IOPORT(W_PowerState) |= 0x0200;
@ -504,20 +438,14 @@ void PowerDown()
} }
bool MACEqual(const u8* a, const u8* b) int Wifi::PreambleLen(int rate)
{
return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]);
}
int PreambleLen(int rate)
{ {
if (rate == 1) return 192; if (rate == 1) return 192;
if (IOPORT(W_Preamble) & 0x0004) return 96; if (IOPORT(W_Preamble) & 0x0004) return 96;
return 192; return 192;
} }
u32 NumClients(u16 bitmask) u32 Wifi::NumClients(u16 bitmask)
{ {
u32 ret = 0; u32 ret = 0;
for (int i = 1; i < 16; i++) for (int i = 1; i < 16; i++)
@ -527,14 +455,14 @@ u32 NumClients(u16 bitmask)
return ret; return ret;
} }
void IncrementTXCount(TXSlot* slot) void Wifi::IncrementTXCount(TXSlot* slot)
{ {
u8 cnt = RAM[slot->Addr + 0x4]; u8 cnt = RAM[slot->Addr + 0x4];
if (cnt < 0xFF) cnt++; if (cnt < 0xFF) cnt++;
*(u16*)&RAM[slot->Addr + 0x4] = cnt; *(u16*)&RAM[slot->Addr + 0x4] = cnt;
} }
void ReportMPReplyErrors(u16 clientfail) void Wifi::ReportMPReplyErrors(u16 clientfail)
{ {
// TODO: do these trigger any IRQ? // TODO: do these trigger any IRQ?
@ -547,7 +475,7 @@ void ReportMPReplyErrors(u16 clientfail)
} }
} }
void TXSendFrame(TXSlot* slot, int num) void Wifi::TXSendFrame(TXSlot* slot, int num)
{ {
u32 noseqno = 0; u32 noseqno = 0;
@ -597,7 +525,7 @@ void TXSendFrame(TXSlot* slot, int num)
case 2: case 2:
case 3: case 3:
Platform::MP_SendPacket(TXBuffer, 12+len, USTimestamp); Platform::MP_SendPacket(TXBuffer, 12+len, USTimestamp);
if (!IsMP) WifiAP::SendPacket(TXBuffer, 12+len); if (!IsMP) WifiAP->SendPacket(TXBuffer, 12+len);
break; break;
case 1: case 1:
@ -617,7 +545,7 @@ void TXSendFrame(TXSlot* slot, int num)
} }
} }
void StartTX_LocN(int nslot, int loc) void Wifi::StartTX_LocN(int nslot, int loc)
{ {
TXSlot* slot = &TXSlots[nslot]; TXSlot* slot = &TXSlots[nslot];
@ -637,7 +565,7 @@ void StartTX_LocN(int nslot, int loc)
slot->CurPhaseTime = PreambleLen(slot->Rate); slot->CurPhaseTime = PreambleLen(slot->Rate);
} }
void StartTX_Cmd() void Wifi::StartTX_Cmd()
{ {
TXSlot* slot = &TXSlots[1]; TXSlot* slot = &TXSlots[1];
@ -672,7 +600,7 @@ void StartTX_Cmd()
} }
} }
void StartTX_Beacon() void Wifi::StartTX_Beacon()
{ {
TXSlot* slot = &TXSlots[4]; TXSlot* slot = &TXSlots[4];
@ -691,7 +619,7 @@ void StartTX_Beacon()
IOPORT(W_TXBusy) |= 0x0010; IOPORT(W_TXBusy) |= 0x0010;
} }
void FireTX() void Wifi::FireTX()
{ {
if (!(IOPORT(W_RXCnt) & 0x8000)) if (!(IOPORT(W_RXCnt) & 0x8000))
return; return;
@ -736,7 +664,7 @@ void FireTX()
} }
} }
void SendMPDefaultReply() void Wifi::SendMPDefaultReply()
{ {
u8 reply[12 + 28]; u8 reply[12 + 28];
@ -766,7 +694,7 @@ void SendMPDefaultReply()
WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen); WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen);
} }
void SendMPReply(u16 clienttime, u16 clientmask) void Wifi::SendMPReply(u16 clienttime, u16 clientmask)
{ {
TXSlot* slot = &TXSlots[5]; TXSlot* slot = &TXSlots[5];
@ -827,7 +755,7 @@ void SendMPReply(u16 clienttime, u16 clientmask)
IOPORT(W_TXBusy) |= 0x0080; IOPORT(W_TXBusy) |= 0x0080;
} }
void SendMPAck(u16 cmdcount, u16 clientfail) void Wifi::SendMPAck(u16 cmdcount, u16 clientfail)
{ {
u8 ack[12 + 32]; u8 ack[12 + 32];
@ -873,10 +801,7 @@ void SendMPAck(u16 cmdcount, u16 clientfail)
WIFI_LOG("wifi: sent %d/44 bytes of MP ack, %d %d\n", txlen, ComStatus, RXTime); WIFI_LOG("wifi: sent %d/44 bytes of MP ack, %d %d\n", txlen, ComStatus, RXTime);
} }
bool CheckRX(int type); bool Wifi::ProcessTX(TXSlot* slot, int num)
void MPClientReplyRX(int client);
bool ProcessTX(TXSlot* slot, int num)
{ {
slot->CurPhaseTime -= kTimerInterval; slot->CurPhaseTime -= kTimerInterval;
if (slot->CurPhaseTime > 0) if (slot->CurPhaseTime > 0)
@ -1137,7 +1062,7 @@ bool ProcessTX(TXSlot* slot, int num)
} }
inline void IncrementRXAddr(u16& addr, u16 inc = 2) inline void Wifi::IncrementRXAddr(u16& addr, u16 inc)
{ {
for (u32 i = 0; i < inc; i += 2) for (u32 i = 0; i < inc; i += 2)
{ {
@ -1148,7 +1073,7 @@ inline void IncrementRXAddr(u16& addr, u16 inc = 2)
} }
} }
void StartRX() void Wifi::StartRX()
{ {
u16 framelen = *(u16*)&RXBuffer[8]; u16 framelen = *(u16*)&RXBuffer[8];
RXTime = framelen; RXTime = framelen;
@ -1176,7 +1101,7 @@ void StartRX()
ComStatus |= 1; ComStatus |= 1;
} }
void FinishRX() void Wifi::FinishRX()
{ {
ComStatus &= ~0x1; ComStatus &= ~0x1;
RXCounter = 0; RXCounter = 0;
@ -1451,7 +1376,7 @@ void FinishRX()
} }
} }
void MPClientReplyRX(int client) void Wifi::MPClientReplyRX(int client)
{ {
if (IOPORT(W_PowerState) & 0x0300) if (IOPORT(W_PowerState) & 0x0300)
return; return;
@ -1492,7 +1417,7 @@ void MPClientReplyRX(int client)
StartRX(); StartRX();
} }
bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames bool Wifi::CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
{ {
if (IOPORT(W_PowerState) & 0x0300) if (IOPORT(W_PowerState) & 0x0300)
return false; return false;
@ -1517,7 +1442,7 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
{ {
rxlen = Platform::MP_RecvPacket(RXBuffer, &timestamp); rxlen = Platform::MP_RecvPacket(RXBuffer, &timestamp);
if ((rxlen <= 0) && (!IsMP)) if ((rxlen <= 0) && (!IsMP))
rxlen = WifiAP::RecvPacket(RXBuffer); rxlen = WifiAP->RecvPacket(RXBuffer);
} }
else else
{ {
@ -1632,7 +1557,7 @@ bool CheckRX(int type) // 0=regular 1=MP replies 2=MP host frames
} }
void MSTimer() void Wifi::MSTimer()
{ {
if (IOPORT(W_USCompareCnt)) if (IOPORT(W_USCompareCnt))
{ {
@ -1656,7 +1581,7 @@ void MSTimer()
} }
} }
void USTimer(u32 param) void Wifi::USTimer(u32 param)
{ {
USTimestamp += kTimerInterval; USTimestamp += kTimerInterval;
@ -1676,7 +1601,7 @@ void USTimer(u32 param)
} }
if (!(USTimestamp & 0x3FF & kTimeCheckMask)) if (!(USTimestamp & 0x3FF & kTimeCheckMask))
WifiAP::MSTimer(); WifiAP->MSTimer();
bool switchOffPowerSaving = false; bool switchOffPowerSaving = false;
if (USUntilPowerOn < 0) if (USUntilPowerOn < 0)
@ -1839,7 +1764,7 @@ void USTimer(u32 param)
} }
void RFTransfer_Type2() void Wifi::RFTransfer_Type2()
{ {
u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F; u32 id = (IOPORT(W_RFData2) >> 2) & 0x1F;
@ -1856,7 +1781,7 @@ void RFTransfer_Type2()
} }
} }
void RFTransfer_Type3() void Wifi::RFTransfer_Type3()
{ {
u32 id = (IOPORT(W_RFData1) >> 8) & 0x3F; u32 id = (IOPORT(W_RFData1) >> 8) & 0x3F;
@ -1873,7 +1798,7 @@ void RFTransfer_Type3()
} }
u16 Read(u32 addr) u16 Wifi::Read(u32 addr)
{ {
if (addr >= 0x04810000) if (addr >= 0x04810000)
return 0; return 0;
@ -1976,7 +1901,7 @@ u16 Read(u32 addr)
return IOPORT(addr&0xFFF); return IOPORT(addr&0xFFF);
} }
void Write(u32 addr, u16 val) void Wifi::Write(u32 addr, u16 val)
{ {
if (addr >= 0x04810000) if (addr >= 0x04810000)
return; return;
@ -2331,14 +2256,12 @@ void Write(u32 addr, u16 val)
} }
u8* GetMAC() u8* Wifi::GetMAC()
{ {
return (u8*)&IOPORT(W_MACAddr0); return (u8*)&IOPORT(W_MACAddr0);
} }
u8* GetBSSID() u8* Wifi::GetBSSID()
{ {
return (u8*)&IOPORT(W_BSSID0); return (u8*)&IOPORT(W_BSSID0);
} }
}

View File

@ -21,178 +21,268 @@
#include "Savestate.h" #include "Savestate.h"
namespace Wifi class WifiAP;
class Wifi
{ {
public:
enum enum
{ {
W_ID = 0x000, W_ID = 0x000,
W_ModeReset = 0x004, W_ModeReset = 0x004,
W_ModeWEP = 0x006, W_ModeWEP = 0x006,
W_TXStatCnt = 0x008, W_TXStatCnt = 0x008,
W_IF = 0x010, W_IF = 0x010,
W_IE = 0x012, W_IE = 0x012,
W_MACAddr0 = 0x018, W_MACAddr0 = 0x018,
W_MACAddr1 = 0x01A, W_MACAddr1 = 0x01A,
W_MACAddr2 = 0x01C, W_MACAddr2 = 0x01C,
W_BSSID0 = 0x020, W_BSSID0 = 0x020,
W_BSSID1 = 0x022, W_BSSID1 = 0x022,
W_BSSID2 = 0x024, W_BSSID2 = 0x024,
W_AIDLow = 0x028, W_AIDLow = 0x028,
W_AIDFull = 0x02A, W_AIDFull = 0x02A,
W_TXRetryLimit = 0x02C, W_TXRetryLimit = 0x02C,
W_RXCnt = 0x030, W_RXCnt = 0x030,
W_WEPCnt = 0x032, W_WEPCnt = 0x032,
W_PowerUS = 0x036, W_PowerUS = 0x036,
W_PowerTX = 0x038, W_PowerTX = 0x038,
W_PowerState = 0x03C, W_PowerState = 0x03C,
W_PowerForce = 0x040, W_PowerForce = 0x040,
W_PowerUnk = 0x48, W_PowerUnk = 0x48,
W_Random = 0x044, W_Random = 0x044,
W_RXBufBegin = 0x050, W_RXBufBegin = 0x050,
W_RXBufEnd = 0x052, W_RXBufEnd = 0x052,
W_RXBufWriteCursor = 0x054, W_RXBufWriteCursor = 0x054,
W_RXBufWriteAddr = 0x056, W_RXBufWriteAddr = 0x056,
W_RXBufReadAddr = 0x058, W_RXBufReadAddr = 0x058,
W_RXBufReadCursor = 0x05A, W_RXBufReadCursor = 0x05A,
W_RXBufCount = 0x05C, W_RXBufCount = 0x05C,
W_RXBufDataRead = 0x060, W_RXBufDataRead = 0x060,
W_RXBufGapAddr = 0x062, W_RXBufGapAddr = 0x062,
W_RXBufGapSize = 0x064, W_RXBufGapSize = 0x064,
W_TXBufWriteAddr = 0x068, W_TXBufWriteAddr = 0x068,
W_TXBufCount = 0x06C, W_TXBufCount = 0x06C,
W_TXBufDataWrite = 0x070, W_TXBufDataWrite = 0x070,
W_TXBufGapAddr = 0x074, W_TXBufGapAddr = 0x074,
W_TXBufGapSize = 0x076, W_TXBufGapSize = 0x076,
W_TXSlotBeacon = 0x080, W_TXSlotBeacon = 0x080,
W_TXBeaconTIM = 0x084, W_TXBeaconTIM = 0x084,
W_ListenCount = 0x088, W_ListenCount = 0x088,
W_BeaconInterval = 0x08C, W_BeaconInterval = 0x08C,
W_ListenInterval = 0x08E, W_ListenInterval = 0x08E,
W_TXSlotCmd = 0x090, W_TXSlotCmd = 0x090,
W_TXSlotReply1 = 0x094, W_TXSlotReply1 = 0x094,
W_TXSlotReply2 = 0x098, W_TXSlotReply2 = 0x098,
W_TXSlotLoc1 = 0x0A0, W_TXSlotLoc1 = 0x0A0,
W_TXSlotLoc2 = 0x0A4, W_TXSlotLoc2 = 0x0A4,
W_TXSlotLoc3 = 0x0A8, W_TXSlotLoc3 = 0x0A8,
W_TXReqReset = 0x0AC, W_TXReqReset = 0x0AC,
W_TXReqSet = 0x0AE, W_TXReqSet = 0x0AE,
W_TXReqRead = 0x0B0, W_TXReqRead = 0x0B0,
W_TXSlotReset = 0x0B4, W_TXSlotReset = 0x0B4,
W_TXBusy = 0x0B6, W_TXBusy = 0x0B6,
W_TXStat = 0x0B8, W_TXStat = 0x0B8,
W_Preamble = 0x0BC, W_Preamble = 0x0BC,
W_CmdTotalTime = 0x0C0, W_CmdTotalTime = 0x0C0,
W_CmdReplyTime = 0x0C4, W_CmdReplyTime = 0x0C4,
W_RXFilter = 0x0D0, W_RXFilter = 0x0D0,
W_RXLenCrop = 0x0DA, W_RXLenCrop = 0x0DA,
W_RXFilter2 = 0x0E0, W_RXFilter2 = 0x0E0,
W_USCountCnt = 0x0E8, W_USCountCnt = 0x0E8,
W_USCompareCnt = 0x0EA, W_USCompareCnt = 0x0EA,
W_CmdCountCnt = 0x0EE, W_CmdCountCnt = 0x0EE,
W_USCount0 = 0x0F8, W_USCount0 = 0x0F8,
W_USCount1 = 0x0FA, W_USCount1 = 0x0FA,
W_USCount2 = 0x0FC, W_USCount2 = 0x0FC,
W_USCount3 = 0x0FE, W_USCount3 = 0x0FE,
W_USCompare0 = 0x0F0, W_USCompare0 = 0x0F0,
W_USCompare1 = 0x0F2, W_USCompare1 = 0x0F2,
W_USCompare2 = 0x0F4, W_USCompare2 = 0x0F4,
W_USCompare3 = 0x0F6, W_USCompare3 = 0x0F6,
W_ContentFree = 0x10C, W_ContentFree = 0x10C,
W_PreBeacon = 0x110, W_PreBeacon = 0x110,
W_CmdCount = 0x118, W_CmdCount = 0x118,
W_BeaconCount1 = 0x11C, W_BeaconCount1 = 0x11C,
W_BeaconCount2 = 0x134, W_BeaconCount2 = 0x134,
W_BBCnt = 0x158, W_BBCnt = 0x158,
W_BBWrite = 0x15A, W_BBWrite = 0x15A,
W_BBRead = 0x15C, W_BBRead = 0x15C,
W_BBBusy = 0x15E, W_BBBusy = 0x15E,
W_BBMode = 0x160, W_BBMode = 0x160,
W_BBPower = 0x168, W_BBPower = 0x168,
W_RFData2 = 0x17C, W_RFData2 = 0x17C,
W_RFData1 = 0x17E, W_RFData1 = 0x17E,
W_RFBusy = 0x180, W_RFBusy = 0x180,
W_RFCnt = 0x184, W_RFCnt = 0x184,
W_TXHeaderCnt = 0x194, W_TXHeaderCnt = 0x194,
W_RFPins = 0x19C, W_RFPins = 0x19C,
W_RXStatIncIF = 0x1A8, W_RXStatIncIF = 0x1A8,
W_RXStatIncIE = 0x1AA, W_RXStatIncIE = 0x1AA,
W_RXStatHalfIF = 0x1AC, W_RXStatHalfIF = 0x1AC,
W_RXStatHalfIE = 0x1AE, W_RXStatHalfIE = 0x1AE,
W_TXErrorCount = 0x1C0, W_TXErrorCount = 0x1C0,
W_RXCount = 0x1C4, W_RXCount = 0x1C4,
W_CMDStat0 = 0x1D0, W_CMDStat0 = 0x1D0,
W_CMDStat1 = 0x1D2, W_CMDStat1 = 0x1D2,
W_CMDStat2 = 0x1D4, W_CMDStat2 = 0x1D4,
W_CMDStat3 = 0x1D6, W_CMDStat3 = 0x1D6,
W_CMDStat4 = 0x1D8, W_CMDStat4 = 0x1D8,
W_CMDStat5 = 0x1DA, W_CMDStat5 = 0x1DA,
W_CMDStat6 = 0x1DC, W_CMDStat6 = 0x1DC,
W_CMDStat7 = 0x1DE, W_CMDStat7 = 0x1DE,
W_TXSeqNo = 0x210, W_TXSeqNo = 0x210,
W_RFStatus = 0x214, W_RFStatus = 0x214,
W_IFSet = 0x21C, W_IFSet = 0x21C,
W_RXTXAddr = 0x268, W_RXTXAddr = 0x268,
};
Wifi();
~Wifi();
void Reset();
void DoSavestate(Savestate* file);
void SetPowerCnt(u32 val);
void USTimer(u32 param);
u16 Read(u32 addr);
void Write(u32 addr, u16 val);
u8* GetMAC();
u8* GetBSSID();
private:
u8 RAM[0x2000];
u16 IO[0x1000>>1];
static const u8 MPCmdMAC[6];
static const u8 MPReplyMAC[6];
static const u8 MPAckMAC[6];
static const int kTimerInterval = 8;
static const u32 kTimeCheckMask = ~(kTimerInterval - 1);
bool Enabled;
bool PowerOn;
s32 TimerError;
u16 Random;
// general, always-on microsecond counter
u64 USTimestamp;
u64 USCounter;
u64 USCompare;
bool BlockBeaconIRQ14;
u32 CmdCounter;
u8 BBRegs[0x100];
u8 BBRegsRO[0x100];
u8 RFVersion;
u32 RFRegs[0x40];
struct TXSlot
{
bool Valid;
u16 Addr;
u16 Length;
u8 Rate;
u8 CurPhase;
int CurPhaseTime;
u32 HalfwordTimeMask;
};
TXSlot TXSlots[6];
u8 TXBuffer[0x2000];
u8 RXBuffer[2048];
u32 RXBufferPtr;
int RXTime;
u32 RXHalfwordTimeMask;
u32 ComStatus; // 0=waiting for packets 1=receiving 2=sending
u32 TXCurSlot;
u32 RXCounter;
int MPReplyTimer;
u16 MPClientMask, MPClientFail;
u8 MPClientReplies[15*1024];
u16 MPLastSeqno;
bool MPInited;
bool LANInited;
int USUntilPowerOn;
bool ForcePowerOn;
// MULTIPLAYER SYNC APPARATUS
bool IsMP;
bool IsMPClient;
u64 NextSync; // for clients: timestamp for next sync point
u64 RXTimestamp;
class WifiAP* WifiAP;
void ScheduleTimer(bool first);
void UpdatePowerOn();
void SetIRQ(u32 irq);
void SetIRQ13();
void SetIRQ14(int source);
void SetIRQ15();
void SetStatus(u32 status);
void PowerDown();
int PreambleLen(int rate);
u32 NumClients(u16 bitmask);
void IncrementTXCount(TXSlot* slot);
void ReportMPReplyErrors(u16 clientfail);
void TXSendFrame(TXSlot* slot, int num);
void StartTX_LocN(int nslot, int loc);
void StartTX_Cmd();
void StartTX_Beacon();
void FireTX();
void SendMPDefaultReply();
void SendMPReply(u16 clienttime, u16 clientmask);
void SendMPAck(u16 cmdcount, u16 clientfail);
bool ProcessTX(TXSlot* slot, int num);
void IncrementRXAddr(u16& addr, u16 inc = 2);
void StartRX();
void FinishRX();
void MPClientReplyRX(int client);
bool CheckRX(int type);
void MSTimer();
void RFTransfer_Type2();
void RFTransfer_Type3();
}; };
enum
{
Event_RXCheck = 0,
Event_IRQ15,
Event_MSTimer,
Event_RFWakeup,
Event_RX,
Event_TX,
Event_MPClientSync,
Event_RF,
Event_BB,
Event_MAX
};
struct SchedEvent
{
void (*Func)(u32 param);
u64 Timestamp;
u32 Param;
};
extern bool MPInited;
bool Init();
void DeInit();
void Reset();
void DoSavestate(Savestate* file);
void SetPowerCnt(u32 val);
void USTimer(u32 param);
u16 Read(u32 addr);
void Write(u32 addr, u16 val);
u8* GetMAC();
u8* GetBSSID();
}
#endif #endif

View File

@ -30,10 +30,9 @@
using Platform::Log; using Platform::Log;
using Platform::LogLevel; using Platform::LogLevel;
namespace WifiAP
{
const u8 APMac[6] = {AP_MAC}; const char* WifiAP::APName = "melonAP";
const u8 WifiAP::APMac[6] = {0x00, 0xF0, 0x77, 0x77, 0x77, 0x77};
#define PWRITE_8(p, v) *p++ = v; #define PWRITE_8(p, v) *p++ = v;
#define PWRITE_16(p, v) *(u16*)p = v; p += 2; #define PWRITE_16(p, v) *(u16*)p = v; p += 2;
@ -65,33 +64,19 @@ const u8 APMac[6] = {AP_MAC};
#define PALIGN_4(p, base) while (PLEN(p,base) & 0x3) *p++ = 0xFF; #define PALIGN_4(p, base) while (PLEN(p,base) & 0x3) *p++ = 0xFF;
u64 USCounter; bool MACEqual(u8* a, const u8* b);
bool MACIsBroadcast(u8* a);
u16 SeqNo;
bool BeaconDue;
u8 PacketBuffer[2048];
int PacketLen;
int RXNum;
u8 LANBuffer[2048];
// this is a lazy AP, we only keep track of one client
// 0=disconnected 1=authenticated 2=associated
int ClientStatus;
bool Init() WifiAP::WifiAP(class Wifi* wifi) : Wifi(wifi)
{
return true;
}
void DeInit()
{ {
} }
void Reset() WifiAP::~WifiAP()
{
}
void WifiAP::Reset()
{ {
// random starting point for the counter // random starting point for the counter
USCounter = 0x428888000ULL; USCounter = 0x428888000ULL;
@ -107,18 +92,7 @@ void Reset()
} }
bool MACEqual(u8* a, u8* b) void WifiAP::MSTimer()
{
return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]);
}
bool MACIsBroadcast(u8* a)
{
return (*(u32*)&a[0] == 0xFFFFFFFF) && (*(u16*)&a[4] == 0xFFFF);
}
void MSTimer()
{ {
USCounter += 0x400; USCounter += 0x400;
@ -131,7 +105,7 @@ void MSTimer()
} }
int HandleManagementFrame(u8* data, int len) int WifiAP::HandleManagementFrame(u8* data, int len)
{ {
// TODO: perfect this // TODO: perfect this
// noting that frames sent pre-auth/assoc don't have a proper BSSID // noting that frames sent pre-auth/assoc don't have a proper BSSID
@ -199,8 +173,8 @@ int HandleManagementFrame(u8* data, int len)
PWRITE_16(p, 0x0021); // capability PWRITE_16(p, 0x0021); // capability
PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates
PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(AP_NAME)); PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME); memcpy(p, APName, strlen(APName)); p += strlen(APName);
PacketLen = PLEN(p, base); PacketLen = PLEN(p, base);
RXNum = 1; RXNum = 1;
@ -282,7 +256,7 @@ int HandleManagementFrame(u8* data, int len)
} }
int SendPacket(u8* data, int len) int WifiAP::SendPacket(u8* data, int len)
{ {
data += 12; data += 12;
@ -330,7 +304,7 @@ int SendPacket(u8* data, int len)
return 0; return 0;
} }
int RecvPacket(u8* data) int WifiAP::RecvPacket(u8* data)
{ {
if (BeaconDue) if (BeaconDue)
{ {
@ -353,8 +327,8 @@ int RecvPacket(u8* data)
PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates PWRITE_8(p, 0x01); PWRITE_8(p, 0x02); PWRITE_8(p, 0x82); PWRITE_8(p, 0x84); // rates
PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel PWRITE_8(p, 0x03); PWRITE_8(p, 0x01); PWRITE_8(p, 0x06); // current channel
PWRITE_8(p, 0x05); PWRITE_8(p, 0x04); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); // TIM PWRITE_8(p, 0x05); PWRITE_8(p, 0x04); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); PWRITE_8(p, 0); // TIM
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(AP_NAME)); PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME); memcpy(p, APName, strlen(APName)); p += strlen(APName);
PALIGN_4(p, base); PALIGN_4(p, base);
PWRITE_32(p, 0xDEADBEEF); // checksum. doesn't matter for now PWRITE_32(p, 0xDEADBEEF); // checksum. doesn't matter for now
@ -394,7 +368,7 @@ int RecvPacket(u8* data)
// check destination MAC // check destination MAC
if (!MACIsBroadcast(&LANBuffer[0])) if (!MACIsBroadcast(&LANBuffer[0]))
{ {
if (!MACEqual(&LANBuffer[0], Wifi::GetMAC())) if (!MACEqual(&LANBuffer[0], Wifi->GetMAC()))
return 0; return 0;
} }
@ -427,5 +401,3 @@ int RecvPacket(u8* data)
return 0; return 0;
} }
}

View File

@ -21,24 +21,44 @@
#include "types.h" #include "types.h"
namespace WifiAP class Wifi;
class WifiAP
{ {
public:
WifiAP(Wifi* wifi);
~WifiAP();
void Reset();
#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77 static const char* APName;
#define AP_NAME "melonAP" static const u8 APMac[6];
extern const u8 APMac[6]; void MSTimer();
bool Init(); // packet format: 12-byte TX header + original 802.11 frame
void DeInit(); int SendPacket(u8* data, int len);
void Reset(); int RecvPacket(u8* data);
void MSTimer(); private:
class Wifi* Wifi;
// packet format: 12-byte TX header + original 802.11 frame u64 USCounter;
int SendPacket(u8* data, int len);
int RecvPacket(u8* data);
} u16 SeqNo;
bool BeaconDue;
u8 PacketBuffer[2048];
int PacketLen;
int RXNum;
u8 LANBuffer[2048];
// this is a lazy AP, we only keep track of one client
// 0=disconnected 1=authenticated 2=associated
int ClientStatus;
int HandleManagementFrame(u8* data, int len);
};
#endif #endif