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

View File

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

View File

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

View File

@ -27,91 +27,19 @@
using Platform::Log;
using Platform::LogLevel;
namespace Wifi
{
//#define WIFI_LOG printf
#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]);
u8 RAM[0x2000];
u16 IO[0x1000>>1];
#define IOPORT(x) IO[(x)>>1]
#define IOPORT8(x) ((u8*)IO)[x]
// destination MACs for MP frames
const u8 MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00};
const u8 MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10};
const u8 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;
const u8 Wifi::MPCmdMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x00};
const u8 Wifi::MPReplyMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x10};
const u8 Wifi::MPAckMAC[6] = {0x03, 0x09, 0xBF, 0x00, 0x00, 0x03};
// multiplayer host TX sequence:
// 1. preamble
@ -148,9 +76,20 @@ u64 RXTimestamp;
// * 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;
//LANInited = false;
@ -161,24 +100,22 @@ bool Init()
Platform::LAN_Init();
LANInited = true;
WifiAP::Init();
return true;
WifiAP = new class WifiAP(this);
}
void DeInit()
Wifi::~Wifi()
{
if (MPInited)
Platform::MP_DeInit();
if (LANInited)
Platform::LAN_DeInit();
WifiAP::DeInit();
delete WifiAP; WifiAP = nullptr;
NDS::UnregisterEventFunc(NDS::Event_Wifi, 0);
}
void Reset()
void Wifi::Reset()
{
memset(RAM, 0, 0x2000);
memset(IO, 0, 0x1000);
@ -277,10 +214,10 @@ void Reset()
NextSync = 0;
RXTimestamp = 0;
WifiAP::Reset();
WifiAP->Reset();
}
void DoSavestate(Savestate* file)
void Wifi::DoSavestate(Savestate* file)
{
file->Section("WIFI");
@ -355,7 +292,7 @@ void DoSavestate(Savestate* file)
}
void ScheduleTimer(bool first)
void Wifi::ScheduleTimer(bool first)
{
if (first) TimerError = 0;
@ -367,7 +304,7 @@ void ScheduleTimer(bool first)
NDS::ScheduleEvent(NDS::Event_Wifi, !first, delay, 0, 0);
}
void UpdatePowerOn()
void Wifi::UpdatePowerOn()
{
bool on = Enabled;
@ -405,17 +342,14 @@ void UpdatePowerOn()
}
}
void SetPowerCnt(u32 val)
void Wifi::SetPowerCnt(u32 val)
{
Enabled = val & (1<<1);
UpdatePowerOn();
}
void PowerDown();
void StartTX_Beacon();
void SetIRQ(u32 irq)
void Wifi::SetIRQ(u32 irq)
{
u32 oldflags = IOPORT(W_IF) & IOPORT(W_IE);
@ -426,7 +360,7 @@ void SetIRQ(u32 irq)
NDS::SetIRQ(1, NDS::IRQ_Wifi);
}
void SetIRQ13()
void Wifi::SetIRQ13()
{
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)
IOPORT(W_BeaconCount1) = IOPORT(W_BeaconInterval);
@ -469,7 +403,7 @@ void SetIRQ14(int source) // 0=USCOMPARE 1=BEACONCOUNT 2=forced
IOPORT(W_ListenCount)--;
}
void SetIRQ15()
void Wifi::SetIRQ15()
{
SetIRQ(15);
@ -481,7 +415,7 @@ void SetIRQ15()
}
void SetStatus(u32 status)
void Wifi::SetStatus(u32 status)
{
// TODO, eventually: states 2/4/7
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_PowerState) |= 0x0200;
@ -504,20 +438,14 @@ void PowerDown()
}
bool MACEqual(const u8* a, const u8* b)
{
return (*(u32*)&a[0] == *(u32*)&b[0]) && (*(u16*)&a[4] == *(u16*)&b[4]);
}
int PreambleLen(int rate)
int Wifi::PreambleLen(int rate)
{
if (rate == 1) return 192;
if (IOPORT(W_Preamble) & 0x0004) return 96;
return 192;
}
u32 NumClients(u16 bitmask)
u32 Wifi::NumClients(u16 bitmask)
{
u32 ret = 0;
for (int i = 1; i < 16; i++)
@ -527,14 +455,14 @@ u32 NumClients(u16 bitmask)
return ret;
}
void IncrementTXCount(TXSlot* slot)
void Wifi::IncrementTXCount(TXSlot* slot)
{
u8 cnt = RAM[slot->Addr + 0x4];
if (cnt < 0xFF) cnt++;
*(u16*)&RAM[slot->Addr + 0x4] = cnt;
}
void ReportMPReplyErrors(u16 clientfail)
void Wifi::ReportMPReplyErrors(u16 clientfail)
{
// 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;
@ -597,7 +525,7 @@ void TXSendFrame(TXSlot* slot, int num)
case 2:
case 3:
Platform::MP_SendPacket(TXBuffer, 12+len, USTimestamp);
if (!IsMP) WifiAP::SendPacket(TXBuffer, 12+len);
if (!IsMP) WifiAP->SendPacket(TXBuffer, 12+len);
break;
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];
@ -637,7 +565,7 @@ void StartTX_LocN(int nslot, int loc)
slot->CurPhaseTime = PreambleLen(slot->Rate);
}
void StartTX_Cmd()
void Wifi::StartTX_Cmd()
{
TXSlot* slot = &TXSlots[1];
@ -672,7 +600,7 @@ void StartTX_Cmd()
}
}
void StartTX_Beacon()
void Wifi::StartTX_Beacon()
{
TXSlot* slot = &TXSlots[4];
@ -691,7 +619,7 @@ void StartTX_Beacon()
IOPORT(W_TXBusy) |= 0x0010;
}
void FireTX()
void Wifi::FireTX()
{
if (!(IOPORT(W_RXCnt) & 0x8000))
return;
@ -736,7 +664,7 @@ void FireTX()
}
}
void SendMPDefaultReply()
void Wifi::SendMPDefaultReply()
{
u8 reply[12 + 28];
@ -766,7 +694,7 @@ void SendMPDefaultReply()
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];
@ -827,7 +755,7 @@ void SendMPReply(u16 clienttime, u16 clientmask)
IOPORT(W_TXBusy) |= 0x0080;
}
void SendMPAck(u16 cmdcount, u16 clientfail)
void Wifi::SendMPAck(u16 cmdcount, u16 clientfail)
{
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);
}
bool CheckRX(int type);
void MPClientReplyRX(int client);
bool ProcessTX(TXSlot* slot, int num)
bool Wifi::ProcessTX(TXSlot* slot, int num)
{
slot->CurPhaseTime -= kTimerInterval;
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)
{
@ -1148,7 +1073,7 @@ inline void IncrementRXAddr(u16& addr, u16 inc = 2)
}
}
void StartRX()
void Wifi::StartRX()
{
u16 framelen = *(u16*)&RXBuffer[8];
RXTime = framelen;
@ -1176,7 +1101,7 @@ void StartRX()
ComStatus |= 1;
}
void FinishRX()
void Wifi::FinishRX()
{
ComStatus &= ~0x1;
RXCounter = 0;
@ -1451,7 +1376,7 @@ void FinishRX()
}
}
void MPClientReplyRX(int client)
void Wifi::MPClientReplyRX(int client)
{
if (IOPORT(W_PowerState) & 0x0300)
return;
@ -1492,7 +1417,7 @@ void MPClientReplyRX(int client)
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)
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);
if ((rxlen <= 0) && (!IsMP))
rxlen = WifiAP::RecvPacket(RXBuffer);
rxlen = WifiAP->RecvPacket(RXBuffer);
}
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))
{
@ -1656,7 +1581,7 @@ void MSTimer()
}
}
void USTimer(u32 param)
void Wifi::USTimer(u32 param)
{
USTimestamp += kTimerInterval;
@ -1676,7 +1601,7 @@ void USTimer(u32 param)
}
if (!(USTimestamp & 0x3FF & kTimeCheckMask))
WifiAP::MSTimer();
WifiAP->MSTimer();
bool switchOffPowerSaving = false;
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;
@ -1856,7 +1781,7 @@ void RFTransfer_Type2()
}
}
void RFTransfer_Type3()
void Wifi::RFTransfer_Type3()
{
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)
return 0;
@ -1976,7 +1901,7 @@ u16 Read(u32 addr)
return IOPORT(addr&0xFFF);
}
void Write(u32 addr, u16 val)
void Wifi::Write(u32 addr, u16 val)
{
if (addr >= 0x04810000)
return;
@ -2331,14 +2256,12 @@ void Write(u32 addr, u16 val)
}
u8* GetMAC()
u8* Wifi::GetMAC()
{
return (u8*)&IOPORT(W_MACAddr0);
}
u8* GetBSSID()
u8* Wifi::GetBSSID()
{
return (u8*)&IOPORT(W_BSSID0);
}
}

View File

@ -21,178 +21,268 @@
#include "Savestate.h"
namespace Wifi
class WifiAP;
class Wifi
{
public:
enum
{
W_ID = 0x000,
enum
{
W_ID = 0x000,
W_ModeReset = 0x004,
W_ModeWEP = 0x006,
W_TXStatCnt = 0x008,
W_IF = 0x010,
W_IE = 0x012,
W_ModeReset = 0x004,
W_ModeWEP = 0x006,
W_TXStatCnt = 0x008,
W_IF = 0x010,
W_IE = 0x012,
W_MACAddr0 = 0x018,
W_MACAddr1 = 0x01A,
W_MACAddr2 = 0x01C,
W_BSSID0 = 0x020,
W_BSSID1 = 0x022,
W_BSSID2 = 0x024,
W_AIDLow = 0x028,
W_AIDFull = 0x02A,
W_MACAddr0 = 0x018,
W_MACAddr1 = 0x01A,
W_MACAddr2 = 0x01C,
W_BSSID0 = 0x020,
W_BSSID1 = 0x022,
W_BSSID2 = 0x024,
W_AIDLow = 0x028,
W_AIDFull = 0x02A,
W_TXRetryLimit = 0x02C,
W_RXCnt = 0x030,
W_WEPCnt = 0x032,
W_TXRetryLimit = 0x02C,
W_RXCnt = 0x030,
W_WEPCnt = 0x032,
W_PowerUS = 0x036,
W_PowerTX = 0x038,
W_PowerState = 0x03C,
W_PowerForce = 0x040,
W_PowerUnk = 0x48,
W_PowerUS = 0x036,
W_PowerTX = 0x038,
W_PowerState = 0x03C,
W_PowerForce = 0x040,
W_PowerUnk = 0x48,
W_Random = 0x044,
W_Random = 0x044,
W_RXBufBegin = 0x050,
W_RXBufEnd = 0x052,
W_RXBufWriteCursor = 0x054,
W_RXBufWriteAddr = 0x056,
W_RXBufReadAddr = 0x058,
W_RXBufReadCursor = 0x05A,
W_RXBufCount = 0x05C,
W_RXBufDataRead = 0x060,
W_RXBufGapAddr = 0x062,
W_RXBufGapSize = 0x064,
W_RXBufBegin = 0x050,
W_RXBufEnd = 0x052,
W_RXBufWriteCursor = 0x054,
W_RXBufWriteAddr = 0x056,
W_RXBufReadAddr = 0x058,
W_RXBufReadCursor = 0x05A,
W_RXBufCount = 0x05C,
W_RXBufDataRead = 0x060,
W_RXBufGapAddr = 0x062,
W_RXBufGapSize = 0x064,
W_TXBufWriteAddr = 0x068,
W_TXBufCount = 0x06C,
W_TXBufDataWrite = 0x070,
W_TXBufGapAddr = 0x074,
W_TXBufGapSize = 0x076,
W_TXBufWriteAddr = 0x068,
W_TXBufCount = 0x06C,
W_TXBufDataWrite = 0x070,
W_TXBufGapAddr = 0x074,
W_TXBufGapSize = 0x076,
W_TXSlotBeacon = 0x080,
W_TXBeaconTIM = 0x084,
W_ListenCount = 0x088,
W_BeaconInterval = 0x08C,
W_ListenInterval = 0x08E,
W_TXSlotCmd = 0x090,
W_TXSlotReply1 = 0x094,
W_TXSlotReply2 = 0x098,
W_TXSlotLoc1 = 0x0A0,
W_TXSlotLoc2 = 0x0A4,
W_TXSlotLoc3 = 0x0A8,
W_TXReqReset = 0x0AC,
W_TXReqSet = 0x0AE,
W_TXReqRead = 0x0B0,
W_TXSlotReset = 0x0B4,
W_TXBusy = 0x0B6,
W_TXStat = 0x0B8,
W_Preamble = 0x0BC,
W_CmdTotalTime = 0x0C0,
W_CmdReplyTime = 0x0C4,
W_RXFilter = 0x0D0,
W_RXLenCrop = 0x0DA,
W_RXFilter2 = 0x0E0,
W_TXSlotBeacon = 0x080,
W_TXBeaconTIM = 0x084,
W_ListenCount = 0x088,
W_BeaconInterval = 0x08C,
W_ListenInterval = 0x08E,
W_TXSlotCmd = 0x090,
W_TXSlotReply1 = 0x094,
W_TXSlotReply2 = 0x098,
W_TXSlotLoc1 = 0x0A0,
W_TXSlotLoc2 = 0x0A4,
W_TXSlotLoc3 = 0x0A8,
W_TXReqReset = 0x0AC,
W_TXReqSet = 0x0AE,
W_TXReqRead = 0x0B0,
W_TXSlotReset = 0x0B4,
W_TXBusy = 0x0B6,
W_TXStat = 0x0B8,
W_Preamble = 0x0BC,
W_CmdTotalTime = 0x0C0,
W_CmdReplyTime = 0x0C4,
W_RXFilter = 0x0D0,
W_RXLenCrop = 0x0DA,
W_RXFilter2 = 0x0E0,
W_USCountCnt = 0x0E8,
W_USCompareCnt = 0x0EA,
W_CmdCountCnt = 0x0EE,
W_USCountCnt = 0x0E8,
W_USCompareCnt = 0x0EA,
W_CmdCountCnt = 0x0EE,
W_USCount0 = 0x0F8,
W_USCount1 = 0x0FA,
W_USCount2 = 0x0FC,
W_USCount3 = 0x0FE,
W_USCompare0 = 0x0F0,
W_USCompare1 = 0x0F2,
W_USCompare2 = 0x0F4,
W_USCompare3 = 0x0F6,
W_USCount0 = 0x0F8,
W_USCount1 = 0x0FA,
W_USCount2 = 0x0FC,
W_USCount3 = 0x0FE,
W_USCompare0 = 0x0F0,
W_USCompare1 = 0x0F2,
W_USCompare2 = 0x0F4,
W_USCompare3 = 0x0F6,
W_ContentFree = 0x10C,
W_PreBeacon = 0x110,
W_CmdCount = 0x118,
W_BeaconCount1 = 0x11C,
W_BeaconCount2 = 0x134,
W_ContentFree = 0x10C,
W_PreBeacon = 0x110,
W_CmdCount = 0x118,
W_BeaconCount1 = 0x11C,
W_BeaconCount2 = 0x134,
W_BBCnt = 0x158,
W_BBWrite = 0x15A,
W_BBRead = 0x15C,
W_BBBusy = 0x15E,
W_BBMode = 0x160,
W_BBPower = 0x168,
W_BBCnt = 0x158,
W_BBWrite = 0x15A,
W_BBRead = 0x15C,
W_BBBusy = 0x15E,
W_BBMode = 0x160,
W_BBPower = 0x168,
W_RFData2 = 0x17C,
W_RFData1 = 0x17E,
W_RFBusy = 0x180,
W_RFCnt = 0x184,
W_RFData2 = 0x17C,
W_RFData1 = 0x17E,
W_RFBusy = 0x180,
W_RFCnt = 0x184,
W_TXHeaderCnt = 0x194,
W_RFPins = 0x19C,
W_TXHeaderCnt = 0x194,
W_RFPins = 0x19C,
W_RXStatIncIF = 0x1A8,
W_RXStatIncIE = 0x1AA,
W_RXStatHalfIF = 0x1AC,
W_RXStatHalfIE = 0x1AE,
W_TXErrorCount = 0x1C0,
W_RXCount = 0x1C4,
W_RXStatIncIF = 0x1A8,
W_RXStatIncIE = 0x1AA,
W_RXStatHalfIF = 0x1AC,
W_RXStatHalfIE = 0x1AE,
W_TXErrorCount = 0x1C0,
W_RXCount = 0x1C4,
W_CMDStat0 = 0x1D0,
W_CMDStat1 = 0x1D2,
W_CMDStat2 = 0x1D4,
W_CMDStat3 = 0x1D6,
W_CMDStat4 = 0x1D8,
W_CMDStat5 = 0x1DA,
W_CMDStat6 = 0x1DC,
W_CMDStat7 = 0x1DE,
W_CMDStat0 = 0x1D0,
W_CMDStat1 = 0x1D2,
W_CMDStat2 = 0x1D4,
W_CMDStat3 = 0x1D6,
W_CMDStat4 = 0x1D8,
W_CMDStat5 = 0x1DA,
W_CMDStat6 = 0x1DC,
W_CMDStat7 = 0x1DE,
W_TXSeqNo = 0x210,
W_RFStatus = 0x214,
W_IFSet = 0x21C,
W_RXTXAddr = 0x268,
W_TXSeqNo = 0x210,
W_RFStatus = 0x214,
W_IFSet = 0x21C,
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

View File

@ -30,10 +30,9 @@
using Platform::Log;
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_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;
u64 USCounter;
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 MACEqual(u8* a, const u8* b);
bool MACIsBroadcast(u8* a);
bool Init()
{
return true;
}
void DeInit()
WifiAP::WifiAP(class Wifi* wifi) : Wifi(wifi)
{
}
void Reset()
WifiAP::~WifiAP()
{
}
void WifiAP::Reset()
{
// random starting point for the counter
USCounter = 0x428888000ULL;
@ -107,18 +92,7 @@ void Reset()
}
bool MACEqual(u8* a, u8* b)
{
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()
void WifiAP::MSTimer()
{
USCounter += 0x400;
@ -131,7 +105,7 @@ void MSTimer()
}
int HandleManagementFrame(u8* data, int len)
int WifiAP::HandleManagementFrame(u8* data, int len)
{
// TODO: perfect this
// 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_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, 0x00); PWRITE_8(p, strlen(AP_NAME));
memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME);
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
memcpy(p, APName, strlen(APName)); p += strlen(APName);
PacketLen = PLEN(p, base);
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;
@ -330,7 +304,7 @@ int SendPacket(u8* data, int len)
return 0;
}
int RecvPacket(u8* data)
int WifiAP::RecvPacket(u8* data)
{
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, 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, 0x00); PWRITE_8(p, strlen(AP_NAME));
memcpy(p, AP_NAME, strlen(AP_NAME)); p += strlen(AP_NAME);
PWRITE_8(p, 0x00); PWRITE_8(p, strlen(APName));
memcpy(p, APName, strlen(APName)); p += strlen(APName);
PALIGN_4(p, base);
PWRITE_32(p, 0xDEADBEEF); // checksum. doesn't matter for now
@ -394,7 +368,7 @@ int RecvPacket(u8* data)
// check destination MAC
if (!MACIsBroadcast(&LANBuffer[0]))
{
if (!MACEqual(&LANBuffer[0], Wifi::GetMAC()))
if (!MACEqual(&LANBuffer[0], Wifi->GetMAC()))
return 0;
}
@ -427,5 +401,3 @@ int RecvPacket(u8* data)
return 0;
}
}

View File

@ -21,24 +21,44 @@
#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
#define AP_NAME "melonAP"
static const char* APName;
static const u8 APMac[6];
extern const u8 APMac[6];
void MSTimer();
bool Init();
void DeInit();
void Reset();
// packet format: 12-byte TX header + original 802.11 frame
int SendPacket(u8* data, int len);
int RecvPacket(u8* data);
void MSTimer();
private:
class Wifi* Wifi;
// packet format: 12-byte TX header + original 802.11 frame
int SendPacket(u8* data, int len);
int RecvPacket(u8* data);
u64 USCounter;
}
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