/* Copyright 2016-2024 melonDS team This file is part of melonDS. melonDS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. melonDS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with melonDS. If not, see http://www.gnu.org/licenses/. */ #ifndef WIFI_H #define WIFI_H #include "Savestate.h" namespace melonDS { class WifiAP; class NDS; class Wifi { public: enum { W_ID = 0x000, 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_TXRetryLimit = 0x02C, W_RXCnt = 0x030, W_WEPCnt = 0x032, W_TRXPower = 0x034, W_PowerUS = 0x036, W_PowerTX = 0x038, W_PowerState = 0x03C, W_PowerForce = 0x040, W_PowerDownCtrl = 0x48, 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_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_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_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_RFData2 = 0x17C, W_RFData1 = 0x17E, W_RFBusy = 0x180, W_RFCnt = 0x184, 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_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, }; Wifi(melonDS::NDS& nds); ~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); const u8* GetMAC() const; const u8* GetBSSID() const; private: melonDS::NDS& NDS; 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]; u32 RFChannelIndex[2]; u32 RFChannelData[14][2]; int CurChannel; 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; int USUntilPowerOn; // 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 CheckIRQ(u16 oldflags); void SetIRQ(u32 irq); void SetIRQ13(); void SetIRQ14(int source); void SetIRQ15(); void SetStatus(u32 status); void UpdatePowerStatus(int power); int PreambleLen(int rate) const; u32 NumClients(u16 bitmask) const; void IncrementTXCount(const TXSlot* slot); void ReportMPReplyErrors(u16 clientfail); void TXSendFrame(const 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 ChangeChannel(); void RFTransfer_Type2(); void RFTransfer_Type3(); }; } #endif