melonDS/src/Wifi.cpp

255 lines
5.1 KiB
C++
Raw Normal View History

2016-12-06 09:32:51 -07:00
/*
Copyright 2016-2017 StapleButter
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/.
*/
#include <stdio.h>
#include <string.h>
#include "NDS.h"
#include "SPI.h"
2016-12-06 09:32:51 -07:00
#include "Wifi.h"
namespace Wifi
{
u8 RAM[0x2000];
u16 IO[0x1000>>1];
#define IOPORT(x) IO[(x)>>1]
u16 Random;
2016-12-06 09:32:51 -07:00
u16 BBCnt;
u8 BBWrite;
u8 BBRegs[0x100];
u8 BBRegsRO[0x100];
u8 RFVersion;
u16 RFCnt;
u16 RFData1;
u16 RFData2;
u32 RFRegs[0x40];
2016-12-06 09:32:51 -07:00
void Reset()
{
memset(RAM, 0, 0x2000);
memset(IO, 0, 0x1000);
Random = 1;
2016-12-06 09:32:51 -07:00
BBCnt = 0;
BBWrite = 0;
memset(BBRegs, 0, 0x100);
memset(BBRegsRO, 0, 0x100);
#define BBREG_FIXED(id, val) BBRegs[id] = val; BBRegsRO[id] = 1;
BBREG_FIXED(0x00, 0x6D);
BBREG_FIXED(0x0D, 0x00);
BBREG_FIXED(0x0E, 0x00);
BBREG_FIXED(0x0F, 0x00);
BBREG_FIXED(0x10, 0x00);
BBREG_FIXED(0x11, 0x00);
BBREG_FIXED(0x12, 0x00);
BBREG_FIXED(0x16, 0x00);
BBREG_FIXED(0x17, 0x00);
BBREG_FIXED(0x18, 0x00);
BBREG_FIXED(0x19, 0x00);
BBREG_FIXED(0x1A, 0x00);
BBREG_FIXED(0x27, 0x00);
BBREG_FIXED(0x4D, 0x00); // 00 or BF
BBREG_FIXED(0x5D, 0x01);
BBREG_FIXED(0x5E, 0x00);
BBREG_FIXED(0x5F, 0x00);
BBREG_FIXED(0x60, 0x00);
BBREG_FIXED(0x61, 0x00);
BBREG_FIXED(0x64, 0xFF); // FF or 3F
BBREG_FIXED(0x66, 0x00);
for (int i = 0x69; i < 0x100; i++)
{
BBREG_FIXED(i, 0x00);
}
#undef BBREG_FIXED
RFVersion = SPI_Firmware::GetRFVersion();
RFCnt = 0;
RFData1 = 0;
RFData2 = 0;
memset(RFRegs, 0, 4*0x40);
memset(&IOPORT(0x018), 0xFF, 6);
memset(&IOPORT(0x020), 0xFF, 6);
}
void RFTransfer_Type2()
{
u32 id = (RFData2 >> 2) & 0x1F;
if (RFData2 & 0x0080)
{
u32 data = RFRegs[id];
RFData1 = data & 0xFFFF;
RFData2 = (RFData2 & 0xFFFC) | ((data >> 16) & 0x3);
}
else
{
u32 data = RFData1 | ((RFData2 & 0x0003) << 16);
RFRegs[id] = data;
}
}
void RFTransfer_Type3()
{
u32 id = (RFData1 >> 8) & 0x3F;
u32 cmd = RFData2 & 0xF;
if (cmd == 6)
{
RFData1 = (RFData1 & 0xFF00) | (RFRegs[id] & 0xFF);
}
else if (cmd == 5)
{
u32 data = RFData1 & 0xFF;
RFRegs[id] = data;
}
2016-12-06 09:32:51 -07:00
}
// TODO: wifi waitstates
2016-12-06 09:32:51 -07:00
u16 Read(u32 addr)
{
addr &= 0x7FFE;
//printf("WIFI: read %08X\n", addr);
if (addr >= 0x4000 && addr < 0x6000)
{
return *(u16*)&RAM[addr & 0x1FFE];
}
2016-12-06 09:32:51 -07:00
switch (addr)
{
case 0x044: // random generator. not accurate
Random = (Random & 0x1) ^ (((Random & 0x3FF) << 1) | (Random >> 10));
return Random;
case 0x0BC:
return IOPORT(0x0BC) & 0x0003;
2016-12-06 09:32:51 -07:00
case 0x158:
return BBCnt;
case 0x15C:
if ((BBCnt & 0xF000) != 0x6000)
{
printf("WIFI: bad BB read, CNT=%04X\n", BBCnt);
return 0;
}
return BBRegs[BBCnt & 0xFF];
case 0x15E:
return 0; // TODO eventually (BB busy flag)
case 0x17C:
return RFData2;
case 0x17E:
return RFData1;
case 0x180:
return 0; // TODO eventually (RF busy flag)
case 0x184:
return RFCnt;
2016-12-06 09:32:51 -07:00
}
//printf("WIFI: read %08X\n", addr);
return IOPORT(addr&0xFFF);
2016-12-06 09:32:51 -07:00
}
void Write(u32 addr, u16 val)
{
addr &= 0x7FFE;
//printf("WIFI: write %08X %04X\n", addr, val);
if (addr >= 0x4000 && addr < 0x6000)
{
*(u16*)&RAM[addr & 0x1FFE] = val;
return;
}
2016-12-06 09:32:51 -07:00
switch (addr)
{
case 0x006:
val &= 0x007F;
break;
case 0x010:
// IF: TODO
return;
case 0x012:
printf("WIFI IE=%04X\n", val);
break;
2016-12-06 09:32:51 -07:00
case 0x158:
BBCnt = val;
if ((BBCnt & 0xF000) == 0x5000)
{
u32 regid = BBCnt & 0xFF;
if (!BBRegsRO[regid])
BBRegs[regid] = val & 0xFF;
}
return;
case 0x15A:
BBWrite = val;
return;
case 0x17C:
RFData2 = val;
if (RFVersion == 3) RFTransfer_Type3();
else RFTransfer_Type2();
return;
case 0x17E:
RFData1 = val;
return;
case 0x184:
RFCnt = val & 0x413F;
return;
// read-only ports
case 0x000:
case 0x044:
case 0x054:
case 0x0B0:
case 0x0B6:
case 0x0B8:
case 0x15C:
case 0x15E:
case 0x180:
case 0x19C:
case 0x1A8:
case 0x1AC:
case 0x1C4:
case 0x210:
case 0x214:
case 0x268:
return;
2016-12-06 09:32:51 -07:00
}
//printf("WIFI: write %08X %04X\n", addr, val);
IOPORT(addr&0xFFF) = val;
2016-12-06 09:32:51 -07:00
}
}