aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNadia Holmquist Pedersen <nadia@nhp.sh>2020-07-26 21:41:09 +0200
committerNadia Holmquist Pedersen <nadia@nhp.sh>2020-07-26 21:41:09 +0200
commitb4ad35948d864cbbb8e1759fbbc913870293160e (patch)
treed5c0ff7f5e4e4388f99650866af063a594aebdab /src
parent0e7df468c761579e9378183ad7f1e8ba3b405ac0 (diff)
parentd9e1bf737c23f688871b2f422bc710777dffbd94 (diff)
Merge remote-tracking branch 'upstream/slirp' into slirp-merge
Diffstat (limited to 'src')
-rw-r--r--src/CP15.cpp8
-rw-r--r--src/DSi.cpp2
-rw-r--r--src/DSi.h2
-rw-r--r--src/DSi_AES.cpp58
-rw-r--r--src/DSi_AES.h2
-rw-r--r--src/DSi_Camera.cpp2
-rw-r--r--src/DSi_Camera.h2
-rw-r--r--src/DSi_I2C.cpp2
-rw-r--r--src/DSi_I2C.h2
-rw-r--r--src/DSi_NDMA.cpp2
-rw-r--r--src/DSi_NDMA.h2
-rw-r--r--src/DSi_NWifi.cpp778
-rw-r--r--src/DSi_NWifi.h29
-rw-r--r--src/DSi_SD.cpp54
-rw-r--r--src/DSi_SD.h7
-rw-r--r--src/DSi_SPI_TSC.cpp2
-rw-r--r--src/DSi_SPI_TSC.h2
-rw-r--r--src/FIFO.h2
-rw-r--r--src/NDS.cpp6
-rw-r--r--src/RTC.cpp4
-rw-r--r--src/SPI.cpp34
-rw-r--r--src/Wifi.cpp2
-rw-r--r--src/WifiAP.cpp15
-rw-r--r--src/WifiAP.h6
-rw-r--r--src/frontend/qt_sdl/CMakeLists.txt6
-rw-r--r--src/frontend/qt_sdl/LAN_Socket.cpp1058
-rw-r--r--src/frontend/qt_sdl/main.cpp6
27 files changed, 1145 insertions, 950 deletions
diff --git a/src/CP15.cpp b/src/CP15.cpp
index 6ac31aa..f6476ab 100644
--- a/src/CP15.cpp
+++ b/src/CP15.cpp
@@ -635,7 +635,10 @@ void ARMv5::CP15Write(u32 id, u32 val)
}
- if ((id&0xF00)!=0x700)
+ if ((id & 0xF00) == 0xF00) // test/debug shit?
+ return;
+
+ if ((id & 0xF00) != 0x700)
printf("unknown CP15 write op %03X %08X\n", id, val);
}
@@ -729,6 +732,9 @@ u32 ARMv5::CP15Read(u32 id)
return ITCMSetting;
}
+ if ((id & 0xF00) == 0xF00) // test/debug shit?
+ return 0;
+
printf("unknown CP15 read op %03X\n", id);
return 0;
}
diff --git a/src/DSi.cpp b/src/DSi.cpp
index 839fdbf..56f5356 100644
--- a/src/DSi.cpp
+++ b/src/DSi.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi.h b/src/DSi.h
index 40f22bb..266b7b4 100644
--- a/src/DSi.h
+++ b/src/DSi.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_AES.cpp b/src/DSi_AES.cpp
index 6a8ffad..dfa67bd 100644
--- a/src/DSi_AES.cpp
+++ b/src/DSi_AES.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
@@ -165,9 +165,37 @@ void ProcessBlock_CCM_Decrypt()
//printf("AES-CCM: "); _printhex2(data, 16);
Swap16(data_rev, data);
+
AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16);
+ for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i];
+ AES_ECB_encrypt(&Ctx, CurMAC);
+
+ Swap16(data, data_rev);
+
+ //printf(" -> "); _printhex2(data, 16);
+
+ OutputFIFO->Write(*(u32*)&data[0]);
+ OutputFIFO->Write(*(u32*)&data[4]);
+ OutputFIFO->Write(*(u32*)&data[8]);
+ OutputFIFO->Write(*(u32*)&data[12]);
+}
+
+void ProcessBlock_CCM_Encrypt()
+{
+ u8 data[16];
+ u8 data_rev[16];
+
+ *(u32*)&data[0] = InputFIFO->Read();
+ *(u32*)&data[4] = InputFIFO->Read();
+ *(u32*)&data[8] = InputFIFO->Read();
+ *(u32*)&data[12] = InputFIFO->Read();
+
+ //printf("AES-CCM: "); _printhex2(data, 16);
+
+ Swap16(data_rev, data);
for (int i = 0; i < 16; i++) CurMAC[i] ^= data_rev[i];
+ AES_CTR_xcrypt_buffer(&Ctx, data_rev, 16);
AES_ECB_encrypt(&Ctx, CurMAC);
Swap16(data, data_rev);
@@ -232,7 +260,6 @@ void WriteCnt(u32 val)
OutputDMASize = dmasize_out[(val >> 14) & 0x3];
AESMode = (val >> 28) & 0x3;
- if (AESMode == 1) printf("AES-CCM TODO\n");
if (val & (1<<24))
{
@@ -245,6 +272,8 @@ void WriteCnt(u32 val)
// transfer start (checkme)
RemBlocks = BlkCnt >> 16;
+ if (AESMode == 0 && (!(val & (1<<20)))) printf("AES: CCM-DECRYPT MAC FROM WRFIFO, TODO\n");
+
if (RemBlocks > 0)
{
u8 key[16];
@@ -365,14 +394,9 @@ void Update()
switch (AESMode)
{
case 0: ProcessBlock_CCM_Decrypt(); break;
+ case 1: ProcessBlock_CCM_Encrypt(); break;
case 2:
case 3: ProcessBlock_CTR(); break;
- default:
- // dorp
- OutputFIFO->Write(InputFIFO->Read());
- OutputFIFO->Write(InputFIFO->Read());
- OutputFIFO->Write(InputFIFO->Read());
- OutputFIFO->Write(InputFIFO->Read());
}
RemBlocks--;
@@ -398,6 +422,24 @@ void Update()
if (CurMAC[15-i] != MAC[i]) Cnt &= ~(1<<21);
}
}
+ else if (AESMode == 1)
+ {
+ Ctx.Iv[13] = 0x00;
+ Ctx.Iv[14] = 0x00;
+ Ctx.Iv[15] = 0x00;
+ AES_CTR_xcrypt_buffer(&Ctx, CurMAC, 16);
+
+ u8 finalmac[16];
+ Swap16(finalmac, CurMAC);
+
+ OutputFIFO->Write(*(u32*)&finalmac[0]);
+ OutputFIFO->Write(*(u32*)&finalmac[4]);
+ OutputFIFO->Write(*(u32*)&finalmac[8]);
+ OutputFIFO->Write(*(u32*)&finalmac[12]);
+
+ // CHECKME
+ Cnt &= ~(1<<21);
+ }
else
{
// CHECKME
diff --git a/src/DSi_AES.h b/src/DSi_AES.h
index 354c4a7..77ef464 100644
--- a/src/DSi_AES.h
+++ b/src/DSi_AES.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_Camera.cpp b/src/DSi_Camera.cpp
index 45061b2..cc44052 100644
--- a/src/DSi_Camera.cpp
+++ b/src/DSi_Camera.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_Camera.h b/src/DSi_Camera.h
index 78629b5..844a4d2 100644
--- a/src/DSi_Camera.h
+++ b/src/DSi_Camera.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_I2C.cpp b/src/DSi_I2C.cpp
index e22c708..d58a38c 100644
--- a/src/DSi_I2C.cpp
+++ b/src/DSi_I2C.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_I2C.h b/src/DSi_I2C.h
index d058be1..35f1ad8 100644
--- a/src/DSi_I2C.h
+++ b/src/DSi_I2C.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_NDMA.cpp b/src/DSi_NDMA.cpp
index 19c72b6..707c777 100644
--- a/src/DSi_NDMA.cpp
+++ b/src/DSi_NDMA.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_NDMA.h b/src/DSi_NDMA.h
index d7b7483..57da289 100644
--- a/src/DSi_NDMA.h
+++ b/src/DSi_NDMA.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_NWifi.cpp b/src/DSi_NWifi.cpp
index 79bc632..73cf4b4 100644
--- a/src/DSi_NWifi.cpp
+++ b/src/DSi_NWifi.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
@@ -21,6 +21,8 @@
#include "DSi.h"
#include "DSi_NWifi.h"
#include "SPI.h"
+#include "WifiAP.h"
+#include "Platform.h"
const u8 CIS0[256] =
@@ -111,15 +113,37 @@ const u8 CIS1[256] =
};
-// hax
-DSi_NWifi* hax_wifi;
-void triggerirq(u32 param)
+DSi_NWifi* Ctx = nullptr;
+
+
+DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
{
- hax_wifi->SetIRQ_F1_Counter(0);
+ // HACK
+ // the mailboxes are supposed to be 0x80 bytes
+ // however, as we do things instantly, emulating this is meaningless
+ // and only adds complication
+ for (int i = 0; i < 8; i++)
+ Mailbox[i] = new FIFO<u8>(0x600);//0x80);
+
+ // extra mailbox acting as a bigger RX buffer
+ Mailbox[8] = new FIFO<u8>(0x8000);
+
+ // this seems to control whether the firmware upload is done
+ EEPROMReady = 0;
+
+ Ctx = this;
}
+DSi_NWifi::~DSi_NWifi()
+{
+ for (int i = 0; i < 9; i++)
+ delete Mailbox[i];
-DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
+ NDS::CancelEvent(NDS::Event_DSi_NWifi);
+ Ctx = nullptr;
+}
+
+void DSi_NWifi::Reset()
{
TransferCmd = 0xFFFFFFFF;
RemSize = 0;
@@ -134,9 +158,8 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
WindowReadAddr = 0;
WindowWriteAddr = 0;
- // TODO: check the actual mailbox size (presumably 0x200)
- for (int i = 0; i < 8; i++)
- Mailbox[i] = new FIFO<u8>(0x200);
+ for (int i = 0; i < 9; i++)
+ Mailbox[i]->Clear();
u8* mac = SPI_Firmware::GetWifiMAC();
printf("NWifi MAC: %02X:%02X:%02X:%02X:%02X:%02X\n",
@@ -158,15 +181,17 @@ DSi_NWifi::DSi_NWifi(DSi_SDHost* host) : DSi_SDDevice(host)
*(u16*)&EEPROM[0x004] = chk;
- EEPROMReady = 0;
-
+ // TODO: SDIO reset shouldn't reset this
+ // this is reset by the internal reset register, and that also resets EEPROM init
BootPhase = 0;
-}
-DSi_NWifi::~DSi_NWifi()
-{
- for (int i = 0; i < 8; i++)
- delete Mailbox[i];
+ ErrorMask = 0;
+ ScanTimer = 0;
+
+ BeaconTimer = 0x10A2220ULL;
+ ConnectionStatus = 0;
+
+ NDS::CancelEvent(NDS::Event_DSi_NWifi);
}
@@ -283,6 +308,7 @@ u8 DSi_NWifi::F1_Read(u32 addr)
if (addr < 0x100)
{
u8 ret = Mailbox[4]->Read();
+ if (addr == 0xFF) DrainRXBuffer();
UpdateIRQ_F1();
return ret;
}
@@ -348,6 +374,7 @@ u8 DSi_NWifi::F1_Read(u32 addr)
else if (addr < 0x1000)
{
u8 ret = Mailbox[4]->Read();
+ if (addr == 0xFFF) DrainRXBuffer();
UpdateIRQ_F1();
return ret;
}
@@ -372,11 +399,12 @@ u8 DSi_NWifi::F1_Read(u32 addr)
else
{
u8 ret = Mailbox[4]->Read();
+ if (addr == 0x3FFF) DrainRXBuffer();
UpdateIRQ_F1();
return ret;
}
- printf("NWIFI: unknown func1 read %05X\n", addr);
+ //printf("NWIFI: unknown func1 read %05X\n", addr);
return 0;
}
@@ -663,13 +691,13 @@ void DSi_NWifi::HandleCommand()
switch (BootPhase)
{
case 0: return BMI_Command();
- case 1: return WMI_Command();
+ case 1: return HTC_Command();
+ case 2: return WMI_Command();
}
}
void DSi_NWifi::BMI_Command()
{
- // HLE command handling stub
u32 cmd = MB_Read32(0);
switch (cmd)
@@ -678,8 +706,8 @@ void DSi_NWifi::BMI_Command()
{
printf("BMI_DONE\n");
EEPROMReady = 1; // GROSS FUCKING HACK
- u8 ready_msg[8] = {0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00};
- SendWMIFrame(ready_msg, 8, 0, 0x00, 0x0000);
+ u8 ready_msg[6] = {0x0A, 0x00, 0x08, 0x06, 0x16, 0x00};
+ SendWMIEvent(0, 0x0001, ready_msg, 6);
BootPhase = 1;
}
return;
@@ -743,7 +771,7 @@ void DSi_NWifi::BMI_Command()
{
u32 len = MB_Read32(0);
printf("BMI LZ write %08X\n", len);
- //FILE* f = fopen("wififirm.bin", "ab");
+ //FILE* f = fopen("debug/wififirm.bin", "ab");
for (int i = 0; i < len; i++)
{
@@ -762,15 +790,13 @@ void DSi_NWifi::BMI_Command()
}
}
-void DSi_NWifi::WMI_Command()
+void DSi_NWifi::HTC_Command()
{
- // HLE command handling stub
u16 h0 = MB_Read16(0);
u16 len = MB_Read16(0);
u16 h2 = MB_Read16(0);
u16 cmd = MB_Read16(0);
- printf("WMI: cmd %04X\n", cmd);
switch (cmd)
{
@@ -778,59 +804,631 @@ void DSi_NWifi::WMI_Command()
{
u16 svc_id = MB_Read16(0);
u16 conn_flags = MB_Read16(0);
-
- u8 svc_resp[10];
- *(u16*)&svc_resp[0] = 0x0003;
- *(u16*)&svc_resp[2] = svc_id;
- svc_resp[4] = 0;
- svc_resp[5] = (svc_id & 0xFF) + 1;
- *(u16*)&svc_resp[6] = 0x0001;
- *(u16*)&svc_resp[8] = 0x0001;
- SendWMIFrame(svc_resp, 10, 0, 0x00, 0x0000);
+ printf("service connect %04X %04X %04X\n", svc_id, conn_flags, MB_Read16(0));
+
+ u8 svc_resp[8];
+ // responses from hardware:
+ // 0003 0100 00 01 0602 00 00
+ // 0003 0101 00 02 0600 00 00
+ // 0003 0102 00 03 0600 00 00
+ // 0003 0103 00 04 0600 00 00
+ // 0003 0104 00 05 0600 00 00
+ *(u16*)&svc_resp[0] = svc_id;
+ svc_resp[2] = 0;
+ svc_resp[3] = (svc_id & 0xFF) + 1;
+ *(u16*)&svc_resp[4] = (svc_id==0x0100) ? 0x0602 : 0x0600; // max message size
+ *(u16*)&svc_resp[6] = 0x0000;
+ SendWMIEvent(0, 0x0003, svc_resp, 8);
}
break;
case 0x0004: // setup complete
{
- u8 ready_evt[14];
- memset(ready_evt, 0, 14);
- *(u16*)&ready_evt[0] = 0x1001;
- memcpy(&ready_evt[2], SPI_Firmware::GetWifiMAC(), 6);
- ready_evt[8] = 0x02;
- *(u32*)&ready_evt[10] = 0x23000024;
- // ctrl[0] = trailer size
- // trailer[1] = trailer extra size
- // trailer[0] = trailer type???
- SendWMIFrame(ready_evt, 14, 1, 0x00, 0x0000);
+ u8 ready_evt[12];
+ memcpy(&ready_evt[0], SPI_Firmware::GetWifiMAC(), 6);
+ ready_evt[6] = 0x02;
+ ready_evt[7] = 0;
+ *(u32*)&ready_evt[8] = 0x2300006C;
+ SendWMIEvent(1, 0x1001, ready_evt, 12);
+
+ u8 regdomain_evt[4];
+ *(u32*)&regdomain_evt[0] = 0x80000000 | (*(u16*)&EEPROM[0x008] & 0x0FFF);
+ SendWMIEvent(1, 0x1006, regdomain_evt, 4);
+
+ BootPhase = 2;
+ NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0);
}
break;
default:
- printf("unknown WMI command %04X\n", cmd);
+ printf("unknown HTC command %04X\n", cmd);
+ for (int i = 0; i < len; i++)
+ {
+ printf("%02X ", Mailbox[0]->Read());
+ if ((i&0xF)==0xF) printf("\n");
+ }
+ printf("\n");
break;
}
MB_Drain(0);
}
-void DSi_NWifi::SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl)
+void DSi_NWifi::WMI_Command()
+{
+ u16 h0 = MB_Read16(0);
+ u16 len = MB_Read16(0);
+ u16 h2 = MB_Read16(0);
+
+ u8 ep = h0 & 0xFF;
+ if (ep > 0x01) // data endpoints
+ {
+ WMI_SendPacket(len);
+ }
+ else
+ {
+ u16 cmd = MB_Read16(0);
+
+ switch (cmd)
+ {
+ case 0x0001: // connect to network
+ {
+ WMI_ConnectToNetwork();
+ }
+ break;
+
+ case 0x0003: // disconnect
+ {
+ if (ConnectionStatus != 1)
+ printf("WMI: ?? trying to disconnect while not connected\n");
+
+ printf("WMI: disconnect\n");
+ ConnectionStatus = 0;
+
+ u8 reply[11];
+ *(u16*)&reply[0] = 3; // checkme
+ memcpy(&reply[2], WifiAP::APMac, 6);
+ reply[8] = 3; // disconnect reason (via cmd)
+ reply[9] = 0; // assoc-response length (none here)
+ reply[10] = 0; // we need atleast one byte here, even if there is no assoc-response
+ SendWMIEvent(1, 0x1003, reply, 11);
+ }
+ break;
+
+ case 0x0004: // synchronize
+ {
+ Mailbox[0]->Read();
+ // TODO??
+ }
+ break;
+
+ case 0x0005: // create priority stream
+ {
+ // TODO???
+ // there's a lot of crap in there.
+ }
+ break;
+
+ case 0x0007: // start scan
+ {
+ u32 forcefg = MB_Read32(0);
+ u32 legacy = MB_Read32(0);
+ u32 scantime = MB_Read32(0);
+ u32 forceinterval = MB_Read32(0);
+ u8 scantype = Mailbox[0]->Read();
+ u8 nchannels = Mailbox[0]->Read();
+
+ printf("WMI: start scan, forceFG=%d, legacy=%d, scanTime=%d, interval=%d, scanType=%d, chan=%d\n",
+ forcefg, legacy, scantime, forceinterval, scantype, nchannels);
+
+ if (ScanTimer > 0)
+ {
+ printf("!! CHECKME: START SCAN BUT WAS ALREADY SCANNING (%d)\n", ScanTimer);
+ }
+
+ // checkme
+ ScanTimer = scantime*5;
+ }
+ break;
+
+ case 0x0008: // set scan params
+ {
+ // TODO: do something with the params!!
+ }
+ break;
+
+ case 0x0009: // set BSS filter
+ {
+ // TODO: do something with the params!!
+ u8 bssfilter = Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ u32 iemask = MB_Read32(0);
+
+ printf("WMI: set BSS filter, filter=%02X, iemask=%08X\n", bssfilter, iemask);
+ }
+ break;
+
+ case 0x000A: // set probed BSSID
+ {
+ u8 id = Mailbox[0]->Read();
+ u8 flags = Mailbox[0]->Read();
+ u8 len = Mailbox[0]->Read();
+
+ char ssid[33] = {0};
+ for (int i = 0; i < len && i < 32; i++)
+ ssid[i] = Mailbox[0]->Read();
+
+ // TODO: store it somewhere
+ printf("WMI: set probed SSID: id=%d, flags=%02X, len=%d, SSID=%s\n", id, flags, len, ssid);
+ }
+ break;
+
+ case 0x000D: // set disconnect timeout
+ {
+ Mailbox[0]->Read();
+ // TODO??
+ }
+ break;
+
+ case 0x000E: // get channel list
+ {
+ int nchan = 11; // TODO: customize??
+ u8 reply[2 + (nchan*2) + 2];
+
+ reply[0] = 0;
+ reply[1] = nchan;
+ for (int i = 0; i < nchan; i++)
+ *(u16*)&reply[2 + (i*2)] = 2412 + (i*5);
+ *(u16*)&reply[2 + (nchan*2)] = 0;
+
+ SendWMIEvent(1, 0x000E, reply, 4+(nchan*2));
+ }
+ break;
+
+ case 0x0011: // set channel params
+ {
+ Mailbox[0]->Read();
+ u8 scan = Mailbox[0]->Read();
+ u8 phymode = Mailbox[0]->Read();
+ u8 len = Mailbox[0]->Read();
+
+ u16 channels[32];
+ for (int i = 0; i < len && i < 32; i++)
+ channels[i] = MB_Read16(0);
+
+ // TODO: store it somewhere
+ printf("WMI: set channel params: scan=%d, phymode=%d, len=%d, channels=", scan, phymode, len);
+ for (int i = 0; i < len && i < 32; i++)
+ printf("%d,", channels[i]);
+ printf("\n");
+ }
+ break;
+
+ case 0x0012: // set power mode
+ {
+ Mailbox[0]->Read();
+ // TODO??
+ }
+ break;
+
+ case 0x0017: // dummy?
+ Mailbox[0]->Read();
+ break;
+
+ case 0x0022: // set error bitmask
+ {
+ ErrorMask = MB_Read32(0);
+ }
+ break;
+
+ case 0x002E: // extension shit
+ {
+ u32 extcmd = MB_Read32(0);
+ switch (extcmd)
+ {
+ case 0x2008: // 'heartbeat'??
+ {
+ u32 cookie = MB_Read32(0);
+ u32 source = MB_Read32(0);
+
+ u8 reply[12];
+ *(u32*)&reply[0] = 0x3007;
+ *(u32*)&reply[4] = cookie;
+ *(u32*)&reply[8] = source;
+
+ SendWMIEvent(1, 0x1010, reply, 12);
+ }
+ break;
+
+ default:
+ printf("WMI: unknown ext cmd 002E:%04X\n", extcmd);
+ break;
+ }
+ }
+ break;
+
+ case 0x003D: // set keepalive interval
+ {
+ Mailbox[0]->Read();
+ // TODO??
+ }
+ break;
+
+ case 0x0041: // 'WMI_SET_WSC_STATUS_CMD'
+ {
+ Mailbox[0]->Read();
+ // TODO??
+ }
+ break;
+
+ case 0x0047: // cmd47 -- timer shenanigans??
+ {
+ //
+ }
+ break;
+
+ case 0x0048: // not supported by DSi??
+ {
+ MB_Read32(0);
+ MB_Read32(0);
+ Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ }
+ break;
+
+ case 0x0049: // 'host exit notify'
+ {
+ //
+ }
+ break;
+
+ case 0xF000: // set bitrate
+ {
+ // TODO!
+ Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ Mailbox[0]->Read();
+ }
+ break;
+
+ default:
+ printf("unknown WMI command %04X (header: %04X:%04X:%04X)\n", cmd, h0, len, h2);
+ for (int i = 0; i < len-2; i++)
+ {
+ printf("%02X ", Mailbox[0]->Read());
+ if ((i&0xF)==0xF) printf("\n");
+ }
+ printf("\n");
+ break;
+ }
+ }
+
+ if (h0 & (1<<8))
+ SendWMIAck(ep);
+
+ MB_Drain(0);
+}
+
+void DSi_NWifi::WMI_ConnectToNetwork()
{
- u32 wlen = 0;
+ u8 type = Mailbox[0]->Read();
+ u8 auth11 = Mailbox[0]->Read();
+ u8 auth = Mailbox[0]->Read();
+ u8 pCryptoType = Mailbox[0]->Read();
+ u8 pCryptoLen = Mailbox[0]->Read();
+ u8 gCryptoType = Mailbox[0]->Read();
+ u8 gCryptoLen = Mailbox[0]->Read();
+ u8 ssidLen = Mailbox[0]->Read();
+
+ char ssid[33] = {0};
+ for (int i = 0; i < 32; i++)
+ ssid[i] = Mailbox[0]->Read();
+ if (ssidLen <= 32)
+ ssid[ssidLen] = '\0';
+
+ u16 channel = MB_Read16(0);
+
+ u8 bssid[6];
+ *(u32*)&bssid[0] = MB_Read32(0);
+ *(u16*)&bssid[4] = MB_Read16(0);
+
+ u32 flags = MB_Read32(0);
+
+ if ((type != 0x01) ||
+ (auth11 != 0x01) ||
+ (auth != 0x01) ||
+ (pCryptoType != 0x01) ||
+ (gCryptoType != 0x01) ||
+ (memcmp(bssid, WifiAP::APMac, 6)))
+ {
+ printf("WMI_Connect: bad parameters\n");
+ // TODO: send disconnect??
+ return;
+ }
+
+ printf("WMI: connecting to network %s\n", ssid);
- Mailbox[4]->Write(ep); // eid
- Mailbox[4]->Write(flags); // flags
- MB_Write16(4, len); // payload length
- MB_Write16(4, ctrl); // ctrl
- wlen += 6;
+ u8 reply[20];
+
+ // hope this is right!
+ *(u16*)&reply[0] = 2437; // channel
+ memcpy(&reply[2], WifiAP::APMac, 6); // BSSID
+ *(u16*)&reply[8] = 128; // listen interval
+ *(u16*)&reply[10] = 128; // beacon interval
+ *(u32*)&reply[12] = 0x01; // network type
+
+ reply[16] = 0x16; // beaconIeLen ???
+ reply[17] = 0x2F; // assocReqLen
+ reply[18] = 0x16; // assocRespLen
+ reply[19] = 0; // ?????
+
+ SendWMIEvent(1, 0x1002, reply, 20);
+
+ ConnectionStatus = 1;
+}
+
+void DSi_NWifi::WMI_SendPacket(u16 len)
+{
+ if (ConnectionStatus != 1)
+ {
+ printf("WMI: !! trying to send shit while not connected\n");
+ // TODO: report error??
+ return;
+ }
+
+ // header???
+ // packets with bit1=1 are something special (sync??)
+ // otherwise, ????
+ // header is 001C on ARP frames, 0000 otherwise
+ u16 hdr = MB_Read16(0);
+ hdr = ((hdr & 0xFF00) >> 8) | ((hdr & 0x00FF) << 8);
+ u16 type = hdr & 0x0003;
+
+ if (type == 2) // data sync
+ {
+ printf("WMI: data sync\n");
+
+ /*Mailbox[8]->Write(2); // eid
+ Mailbox[8]->Write(0x00); // flags
+ MB_Write16(8, 2); // data length
+ Mailbox[8]->Write(0); //
+ Mailbox[8]->Write(0); //
+ MB_Write16(8, 0x0200); //
+
+ DrainRXBuffer();*/
+ return;
+ }
+
+ if (type)
+ {
+ printf("WMI: special frame %04X len=%d\n", hdr, len);
+ for (int i = 0; i < len-2; i++)
+ {
+ printf("%02X ", Mailbox[0]->Read());
+ if ((i&0xF)==0xF) printf("\n");
+ }
+ printf("\n");
+ return;
+ }
+
+ printf("WMI: send packet, hdr=%04X, len=%d\n", hdr, len);
+
+ u8 dstmac[6];
+ u8 srcmac[6];
+ u16 plen;
+
+ *(u32*)&dstmac[0] = MB_Read32(0);
+ *(u16*)&dstmac[4] = MB_Read16(0);
+ *(u32*)&srcmac[0] = MB_Read32(0);
+ *(u16*)&srcmac[4] = MB_Read16(0);
+ plen = MB_Read16(0);
+ plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8);
+
+ if (plen > len-16)
+ {
+ printf("WMI: bad packet length %d > %d\n", plen, len-16);
+ return;
+ }
+
+ u32 h0 = MB_Read32(0);
+ u16 h1 = MB_Read16(0);
+
+ if (h0 != 0x0003AAAA || h1 != 0x0000)
+ {
+ printf("WMI: bad LLC/SLIP header\n");
+ return;
+ }
+
+ u16 ethertype = MB_Read16(0);
+
+ int lan_len = (plen - 8) + 14;
+
+ memcpy(&LANBuffer[0], dstmac, 6); // destination MAC
+ memcpy(&LANBuffer[6], srcmac, 6); // source MAC
+ *(u16*)&LANBuffer[12] = ethertype; // type
+ for (int i = 0; i < lan_len-14; i++)
+ {
+ LANBuffer[14+i] = Mailbox[0]->Read();
+ }
+
+ /*for (int i = 0; i < lan_len; i++)
+ {
+ printf("%02X ", LANBuffer[i]);
+ if ((i&0xF)==0xF) printf("\n");
+ }
+ printf("\n");*/
+
+ Platform::LAN_SendPacket(LANBuffer, lan_len);
+}
+
+void DSi_NWifi::SendWMIEvent(u8 ep, u16 id, u8* data, u32 len)
+{
+ if (!Mailbox[8]->CanFit(6+len+2+8))
+ {
+ printf("NWifi: !! not enough space in RX buffer for WMI event %04X\n", id);
+ return;
+ }
+
+ Mailbox[8]->Write(ep); // eid
+ Mailbox[8]->Write(0x02); // flags (trailer)
+ MB_Write16(8, len+2+8); // data length (plus event ID and trailer)
+ Mailbox[8]->Write(8); // trailer length
+ Mailbox[8]->Write(0); //
+ MB_Write16(8, id); // event ID
for (int i = 0; i < len; i++)
{
- Mailbox[4]->Write(data[i]);
- wlen++;
+ Mailbox[8]->Write(data[i]);
}
- for (; wlen & 0x7F; wlen++)
- Mailbox[4]->Write(0);
+ // trailer
+ Mailbox[8]->Write(0x02);
+ Mailbox[8]->Write(0x06);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+
+ DrainRXBuffer();
+}
+
+void DSi_NWifi::SendWMIAck(u8 ep)
+{
+ if (!Mailbox[8]->CanFit(6+12))
+ {
+ printf("NWifi: !! not enough space in RX buffer for WMI ack (ep #%d)\n", ep);
+ return;
+ }
+
+ Mailbox[8]->Write(0); // eid
+ Mailbox[8]->Write(0x02); // flags (trailer)
+ MB_Write16(8, 0xC); // data length (plus trailer)
+ Mailbox[8]->Write(0xC); // trailer length
+ Mailbox[8]->Write(0); //
+
+ // credit report
+ Mailbox[8]->Write(0x01);
+ Mailbox[8]->Write(0x02);
+ Mailbox[8]->Write(ep);
+ Mailbox[8]->Write(0x01);
+
+ // lookahead
+ Mailbox[8]->Write(0x02);
+ Mailbox[8]->Write(0x06);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+ Mailbox[8]->Write(0x00);
+
+ DrainRXBuffer();
+}
+
+void DSi_NWifi::SendWMIBSSInfo(u8 type, u8* data, u32 len)
+{
+ if (!Mailbox[8]->CanFit(6+len+2+16))
+ {
+ printf("NWifi: !! not enough space in RX buffer for WMI BSSINFO event\n");
+ return;
+ }
+
+ // TODO: check when version>=2 frame type is used?
+ // I observed the version<2 variant on my DSi
+
+ Mailbox[8]->Write(1); // eid
+ Mailbox[8]->Write(0x00); // flags
+ MB_Write16(8, len+2+16); // data length (plus event ID and trailer)
+ Mailbox[8]->Write(0xFF); // trailer length
+ Mailbox[8]->Write(0xFF); //
+ MB_Write16(8, 0x1004); // event ID
+
+ MB_Write16(8, 2437); // channel (6) (checkme!)
+ Mailbox[8]->Write(type);
+ Mailbox[8]->Write(0x1B); // 'snr'
+ MB_Write16(8, 0xFFBC); // RSSI
+ MB_Write32(8, *(u32*)&WifiAP::APMac[0]);
+ MB_Write16(8, *(u16*)&WifiAP::APMac[4]);
+ MB_Write32(8, 0); // ieMask
+
+ for (int i = 0; i < len; i++)
+ {
+ Mailbox[8]->Write(data[i]);
+ }
+
+ DrainRXBuffer();
+}
+
+void DSi_NWifi::CheckRX()
+{
+ if (!Mailbox[8]->CanFit(2048))
+ return;
+
+ int rxlen = Platform::LAN_RecvPacket(LANBuffer);
+ if (rxlen > 0)
+ {
+ //printf("WMI packet recv %04X %04X %04X\n", *(u16*)&LANBuffer[0], *(u16*)&LANBuffer[2], *(u16*)&LANBuffer[4]);
+ // check destination MAC
+ if (*(u32*)&LANBuffer[0] != 0xFFFFFFFF || *(u16*)&LANBuffer[4] != 0xFFFF)
+ {
+ if (memcmp(&LANBuffer[0], &EEPROM[0x00A], 6))
+ return;
+ }
+
+ // check source MAC, in case we get a packet we just sent out
+ if (!memcmp(&LANBuffer[6], &EEPROM[0x00A], 6))
+ return;
+
+ // packet is good
+
+ printf("WMI: receive packet %04X, len=%d\n", *(u16*)&LANBuffer[12], rxlen);
+
+ /*for (int i = 0; i < rxlen; i++)
+ {
+ printf("%02X ", LANBuffer[i]);
+ if ((i&0xF)==0xF) printf("\n");
+ }
+ printf("\n");*/
+
+ int datalen = rxlen - 14; // length of packet body
+
+ u16 hdr = 0x0000;
+ //if (*(u16*)&LANBuffer[12] == 0x0608) // HAX!!!
+ // hdr = 0x1C00;
+ hdr = 0x80;
+
+ // TODO: not hardcode the endpoint ID!!
+ u8 ep = 2;
+
+ Mailbox[8]->Write(ep);
+ Mailbox[8]->Write(0x00);
+ MB_Write16(8, 16 + 8 + datalen);
+ Mailbox[8]->Write(0);
+ Mailbox[8]->Write(0);
+
+ MB_Write16(8, hdr);
+ MB_Write32(8, *(u32*)&LANBuffer[0]);
+ MB_Write16(8, *(u16*)&LANBuffer[4]);
+ MB_Write32(8, *(u32*)&LANBuffer[6]);
+ MB_Write16(8, *(u16*)&LANBuffer[10]);
+ u16 plen = datalen + 8;
+ plen = ((plen & 0xFF00) >> 8) | ((plen & 0x00FF) << 8);
+ MB_Write16(8, plen);
+
+ MB_Write16(8, 0xAAAA);
+ MB_Write16(8, 0x0003);
+ MB_Write16(8, 0x0000);
+ MB_Write16(8, *(u16*)&LANBuffer[12]);
+
+ for (int i = 0; i < datalen; i++)
+ Mailbox[8]->Write(LANBuffer[14+i]);
+
+ DrainRXBuffer();
+ }
}
@@ -849,7 +1447,7 @@ u32 DSi_NWifi::WindowRead(u32 addr)
// base address of EEPROM data
// TODO find what the actual address is!
return 0x1FFC00;
- case 0x58: return EEPROMReady; // hax
+ case 0x58: return EEPROMReady;
}
return 0;
@@ -879,3 +1477,69 @@ void DSi_NWifi::WindowWrite(u32 addr, u32 val)
{
printf("NWifi: window write %08X %08X\n", addr, val);
}
+
+
+void DSi_NWifi::_MSTimer()
+{
+ BeaconTimer++;
+
+ if (ScanTimer > 0)
+ {
+ ScanTimer--;
+
+ // send a beacon
+ if (!(BeaconTimer & 0x7F))
+ {
+ u8 beacon[] =
+ {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // timestamp
+ 0x80, 0x00, // beacon interval
+ 0x21, 0x00, // capability,
+ 0x01, 0x08, 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24, // rates
+ 0x03, 0x01, 0x06, // channel
+ 0x05, 0x04, 0x00, 0x00, 0x00, 0x00, // TIM
+ 0x00, 0x07, 'm', 'e', 'l', 'o', 'n', 'A', 'P', // SSID
+ };
+
+ SendWMIBSSInfo(0x01, beacon, sizeof(beacon));
+ printf("send beacon\n");
+ }
+
+ if (ScanTimer == 0)
+ {
+ u32 status = 0;
+ SendWMIEvent(1, 0x100A, (u8*)&status, 4);
+ }
+ }
+
+ if (ConnectionStatus == 1)
+ {
+ //if (Mailbox[4]->IsEmpty())
+ CheckRX();
+ }
+}
+
+void DSi_NWifi::DrainRXBuffer()
+{
+ while (Mailbox[8]->Level() >= 6)
+ {
+ u16 len = Mailbox[8]->Peek(2) | (Mailbox[8]->Peek(3) << 8);
+ u32 totallen = len + 6;
+ u32 required = (totallen + 0x7F) & ~0x7F;
+
+ if (!Mailbox[4]->CanFit(required))
+ break;
+
+ u32 i = 0;
+ for (; i < totallen; i++) Mailbox[4]->Write(Mailbox[8]->Read());
+ for (; i < required; i++) Mailbox[4]->Write(0);
+ }
+
+ UpdateIRQ_F1();
+}
+
+void DSi_NWifi::MSTimer(u32 param)
+{
+ Ctx->_MSTimer();
+ NDS::ScheduleEvent(NDS::Event_DSi_NWifi, true, 33611, MSTimer, 0);
+}
diff --git a/src/DSi_NWifi.h b/src/DSi_NWifi.h
index e5fe637..a72d54d 100644
--- a/src/DSi_NWifi.h
+++ b/src/DSi_NWifi.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
@@ -28,6 +28,8 @@ public:
DSi_NWifi(DSi_SDHost* host);
~DSi_NWifi();
+ void Reset();
+
void SendCMD(u8 cmd, u32 param);
void SendACMD(u8 cmd, u32 param);
@@ -35,6 +37,10 @@ public:
void SetIRQ_F1_Counter(u32 n);
+ void _MSTimer();
+
+ static void MSTimer(u32 param);
+
private:
u32 TransferCmd;
u32 TransferAddr;
@@ -60,9 +66,18 @@ private:
void HandleCommand();
void BMI_Command();
+ void HTC_Command();
void WMI_Command();
- void SendWMIFrame(u8* data, u32 len, u8 ep, u8 flags, u16 ctrl);
+ void WMI_ConnectToNetwork();
+ void WMI_SendPacket(u16 len);
+
+ void SendWMIEvent(u8 ep, u16 id, u8* data, u32 len);
+ void SendWMIAck(u8 ep);
+ void SendWMIBSSInfo(u8 type, u8* data, u32 len);
+
+ void CheckRX();
+ void DrainRXBuffer();
u32 WindowRead(u32 addr);
void WindowWrite(u32 addr, u32 val);
@@ -102,7 +117,7 @@ private:
while (!Mailbox[n]->IsEmpty()) Mailbox[n]->Read();
}
- FIFO<u8>* Mailbox[8];
+ FIFO<u8>* Mailbox[9];
u8 F0_IRQEnable;
u8 F0_IRQStatus;
@@ -116,6 +131,14 @@ private:
u32 EEPROMReady;
u32 BootPhase;
+
+ u32 ErrorMask;
+ u32 ScanTimer;
+
+ u64 BeaconTimer;
+ u32 ConnectionStatus;
+
+ u8 LANBuffer[2048];
};
#endif // DSI_NWIFI_H
diff --git a/src/DSi_SD.cpp b/src/DSi_SD.cpp
index 7fdba0f..def7a33 100644
--- a/src/DSi_SD.cpp
+++ b/src/DSi_SD.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
@@ -112,8 +112,8 @@ void DSi_SDHost::Reset()
if (Ports[0]) delete Ports[0];
if (Ports[1]) delete Ports[1];
- Ports[0] = NULL;
- Ports[1] = NULL;
+ Ports[0] = nullptr;
+ Ports[1] = nullptr;
if (Num == 0)
{
@@ -135,6 +135,9 @@ void DSi_SDHost::Reset()
Ports[0] = nwifi;
}
+
+ if (Ports[0]) Ports[0]->Reset();
+ if (Ports[1]) Ports[1]->Reset();
}
void DSi_SDHost::DoSavestate(Savestate* file)
@@ -205,6 +208,18 @@ void DSi_SDHost::SetCardIRQ()
}
}
+void DSi_SDHost::UpdateCardIRQ(u16 oldmask)
+{
+ u16 oldflags = CardIRQStatus & ~oldmask;
+ u16 newflags = CardIRQStatus & ~CardIRQMask;
+
+ if ((oldflags == 0) && (newflags != 0)) // checkme
+ {
+ NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO : NDS::IRQ2_DSi_SDMMC);
+ NDS::SetIRQ2(Num ? NDS::IRQ2_DSi_SDIO_Data1 : NDS::IRQ2_DSi_SD_Data1);
+ }
+}
+
void DSi_SDHost::SendResponse(u32 val, bool last)
{
*(u32*)&ResponseBuffer[6] = *(u32*)&ResponseBuffer[4];
@@ -448,6 +463,7 @@ u16 DSi_SDHost::Read(u32 addr)
case 0x0F6: return 0; // MMC write protect (always 0)
case 0x100: return Data32IRQ;
+ case 0x102: return 0;
case 0x104: return BlockLen32;
case 0x108: return BlockCount32;
}
@@ -549,8 +565,8 @@ void DSi_SDHost::Write(u32 addr, u16 val)
u32 oldmask = IRQMask;
IRQMask = (IRQMask & 0x0000031D) | ((val & 0x8B7F) << 16);
UpdateIRQ(oldmask);
- if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme
- if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme
+ //if (!DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(24); // checkme
+ //if (DataFIFO[CurFIFO]->IsEmpty()) SetIRQ(25); // checkme
}
return;
@@ -571,8 +587,13 @@ void DSi_SDHost::Write(u32 addr, u16 val)
CardIRQStatus &= val;
return;
case 0x038:
- CardIRQMask = val & 0xC007;
- SetCardIRQ();
+ {
+ u16 oldmask = CardIRQMask;
+ CardIRQMask = val & 0xC007;
+ UpdateCardIRQ(oldmask);
+ }
+ //CardIRQMask = val & 0xC007;
+ //SetCardIRQ();
return;
case 0x0D8:
@@ -592,6 +613,9 @@ void DSi_SDHost::Write(u32 addr, u16 val)
SDOption = 0x40EE;
// TODO: CARD_IRQ_STAT
// TODO: FIFO16 shit
+
+ if (Ports[0]) Ports[0]->Reset();
+ if (Ports[1]) Ports[1]->Reset();
}
SoftReset = 0x0006 | (val & 0x0001);
return;
@@ -601,6 +625,7 @@ void DSi_SDHost::Write(u32 addr, u16 val)
if (val & (1<<10)) DataFIFO32->Clear();
DataMode = ((DataCtl >> 1) & 0x1) & ((Data32IRQ >> 1) & 0x1);
return;
+ case 0x102: return;
case 0x104: BlockLen32 = val & 0x03FF; return;
case 0x108: BlockCount32 = val; return;
}
@@ -701,6 +726,16 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path
File = Platform::OpenLocalFile(path, "w+b");
}
}
+}
+
+DSi_MMCStorage::~DSi_MMCStorage()
+{
+ if (File) fclose(File);
+}
+
+void DSi_MMCStorage::Reset()
+{
+ // TODO: reset file access????
CSR = 0x00000100; // checkme
@@ -723,11 +758,6 @@ DSi_MMCStorage::DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path
RWCommand = 0;
}
-DSi_MMCStorage::~DSi_MMCStorage()
-{
- if (File) fclose(File);
-}
-
void DSi_MMCStorage::SendCMD(u8 cmd, u32 param)
{
if (CSR & (1<<5))
diff --git a/src/DSi_SD.h b/src/DSi_SD.h
index 2862173..30da6c7 100644
--- a/src/DSi_SD.h
+++ b/src/DSi_SD.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
@@ -95,6 +95,7 @@ private:
void ClearIRQ(u32 irq);
void SetIRQ(u32 irq);
void UpdateIRQ(u32 oldmask);
+ void UpdateCardIRQ(u16 oldmask);
};
@@ -104,6 +105,8 @@ public:
DSi_SDDevice(DSi_SDHost* host) { Host = host; IRQ = false; }
~DSi_SDDevice() {}
+ virtual void Reset() = 0;
+
virtual void SendCMD(u8 cmd, u32 param) = 0;
virtual void ContinueTransfer() = 0;
@@ -120,6 +123,8 @@ public:
DSi_MMCStorage(DSi_SDHost* host, bool internal, const char* path);
~DSi_MMCStorage();
+ void Reset();
+
void SetCID(u8* cid) { memcpy(CID, cid, 16); }
void SendCMD(u8 cmd, u32 param);
diff --git a/src/DSi_SPI_TSC.cpp b/src/DSi_SPI_TSC.cpp
index 507005b..adff4a3 100644
--- a/src/DSi_SPI_TSC.cpp
+++ b/src/DSi_SPI_TSC.cpp
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/DSi_SPI_TSC.h b/src/DSi_SPI_TSC.h
index f3ffc32..c8e1164 100644
--- a/src/DSi_SPI_TSC.h
+++ b/src/DSi_SPI_TSC.h
@@ -1,5 +1,5 @@
/*
- Copyright 2016-2019 Arisotura
+ Copyright 2016-2020 Arisotura
This file is part of melonDS.
diff --git a/src/FIFO.h b/src/FIFO.h
index fe0b2aa..2b2c102 100644
--- a/src/FIFO.h
+++ b/src/FIFO.h
@@ -102,6 +102,8 @@ public:
bool IsEmpty() { return NumOccupied == 0; }
bool IsFull() { return NumOccupied >= NumEntries; }
+ bool CanFit(u32 num) { return ((NumOccupied + num) <= NumEntries); }
+
private:
u32 NumEntries;
T* Entries;
diff --git a/src/NDS.cpp b/src/NDS.cpp
index 18ae3e9..65c3223 100644
--- a/src/NDS.cpp
+++ b/src/NDS.cpp
@@ -1815,14 +1815,14 @@ void debug(u32 param)
}
fclose(shit);*/
FILE*
- /*shit = fopen("debug/dump9.bin", "wb");
+ shit = fopen("debug/dump9.bin", "wb");
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
{
u32 val = DSi::ARM9Read32(i);
fwrite(&val, 4, 1, shit);
}
- fclose(shit);*/
- shit = fopen("debug/dump7_2.bin", "wb");
+ fclose(shit);
+ shit = fopen("debug/dump7.bin", "wb");
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
{
u32 val = DSi::ARM7Read32(i);
diff --git a/src/RTC.cpp b/src/RTC.cpp
index 0d80b2c..ba51dff 100644
--- a/src/RTC.cpp
+++ b/src/RTC.cpp
@@ -106,7 +106,6 @@ u8 BCD(u8 val)
void ByteIn(u8 val)
{
- //printf("RTC IN: %02X\n", val);
if (InputPos == 0)
{
if ((val & 0xF0) == 0x60)
@@ -175,7 +174,6 @@ void ByteIn(u8 val)
case 0x70: Output[0] = FreeReg; break;
}
}
- InputPos++;
return;
}
@@ -221,8 +219,6 @@ void ByteIn(u8 val)
if (InputPos == 1) FreeReg = val;
break;
}
-
- InputPos++;
}
diff --git a/src/SPI.cpp b/src/SPI.cpp
index ac40707..eff0a05 100644
--- a/src/SPI.cpp
+++ b/src/SPI.cpp
@@ -162,22 +162,26 @@ void Reset()
UserSettings = userdata;
- // fix touchscreen coords
- #if 0
- *(u16*)&Firmware[userdata+0x58] = 0;
- *(u16*)&Firmware[userdata+0x5A] = 0;
- Firmware[userdata+0x5C] = 0;
- Firmware[userdata+0x5D] = 0;
- *(u16*)&Firmware[userdata+0x5E] = 255<<4;
- *(u16*)&Firmware[userdata+0x60] = 191<<4;
- Firmware[userdata+0x62] = 255;
- Firmware[userdata+0x63] = 191;
-
- // disable autoboot
- //Firmware[userdata+0x64] &= 0xBF;
-
- *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
+ // TODO evetually: do this in DSi mode
+ if (NDS::ConsoleType == 0)
+ {
+ // fix touchscreen coords
+ *(u16*)&Firmware[userdata+0x58] = 0;
+ *(u16*)&Firmware[userdata+0x5A] = 0;
+ Firmware[userdata+0x5C] = 0;
+ Firmware[userdata+0x5D] = 0;
+ *(u16*)&Firmware[userdata+0x5E] = 255<<4;
+ *(u16*)&Firmware[userdata+0x60] = 191<<4;
+ Firmware[userdata+0x62] = 255;
+ Firmware[userdata+0x63] = 191;
+
+ // disable autoboot
+ //Firmware[userdata+0x64] &= 0xBF;
+
+ *(u16*)&Firmware[userdata+0x72] = CRC16(&Firmware[userdata], 0x70, 0xFFFF);
+ }
+#if 0
// replace MAC address with random address
// TODO: make optional?
Firmware[0x36] = 0x00;
diff --git a/src/Wifi.cpp b/src/Wifi.cpp
index ab82724..8188151 100644
--- a/src/Wifi.cpp
+++ b/src/Wifi.cpp
@@ -188,6 +188,8 @@ void Reset()
IOPORT(0x000) = 0x1440;
else if (console == 0x20)
IOPORT(0x000) = 0xC340;
+ else if (NDS::ConsoleType == 1 && console == 0x57)
+ IOPORT(0x000) = 0xC340; // DSi has the modern DS-wifi variant
else
{
printf("wifi: unknown console type %02X\n", console);
diff --git a/src/WifiAP.cpp b/src/WifiAP.cpp
index 3a5de37..ae9664c 100644
--- a/src/WifiAP.cpp
+++ b/src/WifiAP.cpp
@@ -30,9 +30,6 @@
namespace WifiAP
{
-#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77
-#define AP_NAME "melonAP"
-
const u8 APMac[6] = {AP_MAC};
#define PWRITE_8(p, v) *p++ = v;
@@ -130,6 +127,18 @@ void USTimer()
}
}
+void MSTimer()
+{
+ USCounter += 0x400;
+
+ u32 chk = (u32)USCounter;
+ if (!(chk & 0x1FC00))
+ {
+ // send beacon every 128ms
+ BeaconDue = true;
+ }
+}
+
int HandleManagementFrame(u8* data, int len)
{
diff --git a/src/WifiAP.h b/src/WifiAP.h
index 97946a5..130383e 100644
--- a/src/WifiAP.h
+++ b/src/WifiAP.h
@@ -22,11 +22,17 @@
namespace WifiAP
{
+#define AP_MAC 0x00, 0xF0, 0x77, 0x77, 0x77, 0x77
+#define AP_NAME "melonAP"
+
+extern const u8 APMac[6];
+
bool Init();
void DeInit();
void Reset();
void USTimer();
+void MSTimer();
// packet format: 12-byte TX header + original 802.11 frame
int SendPacket(u8* data, int len);
diff --git a/src/frontend/qt_sdl/CMakeLists.txt b/src/frontend/qt_sdl/CMakeLists.txt
index ea7849f..7451307 100644
--- a/src/frontend/qt_sdl/CMakeLists.txt
+++ b/src/frontend/qt_sdl/CMakeLists.txt
@@ -47,6 +47,7 @@ set(CMAKE_AUTORCC ON)
find_package(Threads REQUIRED)
find_package(PkgConfig REQUIRED)
pkg_check_modules(SDL2 REQUIRED sdl2)
+pkg_check_modules(SLIRP REQUIRED slirp)
if (WIN32 AND (CMAKE_BUILD_TYPE STREQUAL Release))
add_executable(melonDS WIN32 ${SOURCES_QT_SDL})
@@ -57,15 +58,16 @@ endif()
target_link_libraries(melonDS ${CMAKE_THREAD_LIBS_INIT})
target_include_directories(melonDS PRIVATE ${SDL2_INCLUDE_DIRS})
+target_include_directories(melonDS PRIVATE ${SLIRP_INCLUDE_DIRS})
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/..")
target_include_directories(melonDS PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../..")
target_link_libraries(melonDS core)
if (BUILD_STATIC)
- target_link_libraries(melonDS -static ${SDL2_LIBRARIES})
+ target_link_libraries(melonDS -static ${SDL2_STATIC_LIBRARIES} ${SLIRP_STATIC_LIBRARIES})
else()
- target_link_libraries(melonDS ${SDL2_LIBRARIES})
+ target_link_libraries(melonDS ${SDL2_LIBRARIES} ${SLIRP_LIBRARIES})
endif()
if (UNIX)
diff --git a/src/frontend/qt_sdl/LAN_Socket.cpp b/src/frontend/qt_sdl/LAN_Socket.cpp
index c6fbd4b..458c931 100644
--- a/src/frontend/qt_sdl/LAN_Socket.cpp
+++ b/src/frontend/qt_sdl/LAN_Socket.cpp
@@ -21,30 +21,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "../Wifi.h"
+#include "Wifi.h"
#include "LAN_Socket.h"
-#include "../Config.h"
+#include "Config.h"
+#include "FIFO.h"
+
+#include <slirp/libslirp.h>
#ifdef __WIN32__
- #include <winsock2.h>
#include <ws2tcpip.h>
- #define socket_t SOCKET
- #define sockaddr_t SOCKADDR
#else
- #include <unistd.h>
- #include <arpa/inet.h>
- #include <netinet/in.h>
- #include <sys/types.h>
- #include <sys/select.h>
#include <sys/socket.h>
#include <netdb.h>
- #define socket_t int
- #define sockaddr_t struct sockaddr
- #define closesocket close
-#endif
-
-#ifndef INVALID_SOCKET
-#define INVALID_SOCKET (socket_t)-1
+ #include <poll.h>
+ #include <time.h>
#endif
@@ -57,85 +47,192 @@ const u32 kDNSIP = kSubnet | 0x02;
const u32 kClientIP = kSubnet | 0x10;
const u8 kServerMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x44};
-const u8 kDNSMAC[6] = {0x00, 0xAB, 0x33, 0x28, 0x99, 0x55};
-u8 PacketBuffer[2048];
-int PacketLen;
-volatile int RXNum;
+FIFO<u32>* RXBuffer = nullptr;
+
+u32 IPv4ID;
+
+Slirp* Ctx = nullptr;
+
+/*const int FDListMax = 64;
+struct pollfd FDList[FDListMax];
+int FDListSize;*/
+
+
+#ifdef __WIN32__
+
+#define poll WSAPoll
+
+// https://stackoverflow.com/questions/5404277/porting-clock-gettime-to-windows
+
+struct timespec { long tv_sec; long tv_nsec; };
+#define CLOCK_MONOTONIC 1312
+
+int clock_gettime(int, struct timespec *spec)
+{
+ __int64 wintime;
+ GetSystemTimeAsFileTime((FILETIME*)&wintime);
+ wintime -=116444736000000000LL; //1jan1601 to 1jan1970
+ spec->tv_sec = wintime / 10000000LL; //seconds
+ spec->tv_nsec = wintime % 10000000LL * 100; //nano-seconds
+ return 0;
+}
+
+#endif // __WIN32__
+
+
+void RXEnqueue(const void* buf, int len)
+{
+ int alignedlen = (len + 3) & ~3;
+ int totallen = alignedlen + 4;
+
+ if (!RXBuffer->CanFit(totallen >> 2))
+ {
+ printf("slirp: !! NOT ENOUGH SPACE IN RX BUFFER\n");
+ return;
+ }
+
+ u32 header = (alignedlen & 0xFFFF) | (len << 16);
+ RXBuffer->Write(header);
+ for (int i = 0; i < alignedlen; i += 4)
+ RXBuffer->Write(((u32*)buf)[i>>2]);
+}
-u16 IPv4ID;
+ssize_t SlirpCbSendPacket(const void* buf, size_t len, void* opaque)
+{
+ if (len > 2048)
+ {
+ printf("slirp: packet too big (%d)\n", len);
+ return 0;
+ }
+ printf("slirp: response packet of %d bytes, type %04X\n", len, ntohs(((u16*)buf)[6]));
-// TODO: UDP sockets
-// * use FIFO list
-// * assign new socket when seeing new IP/port
+ RXEnqueue(buf, len);
+ return len;
+}
-typedef struct
+void SlirpCbGuestError(const char* msg, void* opaque)
{
- u8 DestIP[4];
- u16 SourcePort;
- u16 DestPort;
+ printf("SLIRP: error: %s\n", msg);
+}
- u32 SeqNum; // sequence number for incoming frames
- u32 AckNum;
+int64_t SlirpCbClockGetNS(void* opaque)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+}
- // 0: unused
- // 1: connected
- u8 Status;
+void* SlirpCbTimerNew(SlirpTimerCb cb, void* cb_opaque, void* opaque)
+{
+ return nullptr;
+}
- socket_t Backend;
+void SlirpCbTimerFree(void* timer, void* opaque)
+{
+}
-} TCPSocket;
+void SlirpCbTimerMod(void* timer, int64_t expire_time, void* opaque)
+{
+}
-typedef struct
+void SlirpCbRegisterPollFD(int fd, void* opaque)
{
- u8 DestIP[4];
- u16 SourcePort;
- u16 DestPort;
+ printf("Slirp: register poll FD %d\n", fd);
+
+ /*if (FDListSize >= FDListMax)
+ {
+ printf("!! SLIRP FD LIST FULL\n");
+ return;
+ }
+
+ for (int i = 0; i < FDListSize; i++)
+ {
+ if (FDList[i].fd == fd) return;
+ }
- socket_t Backend;
- struct sockaddr_in BackendAddr;
+ FDList[FDListSize].fd = fd;
+ FDListSize++;*/
+}
-} UDPSocket;
+void SlirpCbUnregisterPollFD(int fd, void* opaque)
+{
+ printf("Slirp: unregister poll FD %d\n", fd);
-TCPSocket TCPSocketList[16];
-UDPSocket UDPSocketList[4];
+ /*if (FDListSize < 1)
+ {
+ printf("!! SLIRP FD LIST EMPTY\n");
+ return;
+ }
-int UDPSocketID = 0;
+ for (int i = 0; i < FDListSize; i++)
+ {
+ if (FDList[i].fd == fd)
+ {
+ FDListSize--;
+ FDList[i] = FDList[FDListSize];
+ }
+ }*/
+}
+void SlirpCbNotify(void* opaque)
+{
+ printf("Slirp: notify???\n");
+}
+
+SlirpCb cb =
+{
+ .send_packet = SlirpCbSendPacket,
+ .guest_error = SlirpCbGuestError,
+ .clock_get_ns = SlirpCbClockGetNS,
+ .timer_new = SlirpCbTimerNew,
+ .timer_free = SlirpCbTimerFree,
+ .timer_mod = SlirpCbTimerMod,
+ .register_poll_fd = SlirpCbRegisterPollFD,
+ .unregister_poll_fd = SlirpCbUnregisterPollFD,
+ .notify = SlirpCbNotify
+};
bool Init()
{
- // TODO: how to deal with cases where an adapter is unplugged or changes config??
- //if (PCapLib) return true;
+ IPv4ID = 0;
+
+ //FDListSize = 0;
+ //memset(FDList, 0, sizeof(FDList));
- //Lib = NULL;
- PacketLen = 0;
- RXNum = 0;
+ RXBuffer = new FIFO<u32>(0x8000 >> 2);
- IPv4ID = 1;
+ SlirpConfig cfg;
+ memset(&cfg, 0, sizeof(cfg));
+ cfg.version = 1;
- memset(TCPSocketList, 0, sizeof(TCPSocketList));
- memset(UDPSocketList, 0, sizeof(UDPSocketList));
+ cfg.in_enabled = true;
+ *(u32*)&cfg.vnetwork = htonl(kSubnet);
+ *(u32*)&cfg.vnetmask = htonl(0xFFFFFF00);
+ *(u32*)&cfg.vhost = htonl(kServerIP);
+ cfg.vhostname = "melonServer";
+ *(u32*)&cfg.vdhcp_start = htonl(kClientIP);
+ *(u32*)&cfg.vnameserver = htonl(kDNSIP);
- UDPSocketID = 0;
+ Ctx = slirp_new(&cfg, &cb, nullptr);
return true;
}
void DeInit()
{
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
+ if (Ctx)
{
- TCPSocket* sock = &TCPSocketList[i];
- if (sock->Backend) closesocket(sock->Backend);
+ slirp_cleanup(Ctx);
+ Ctx = nullptr;
}
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (RXBuffer)
{
- UDPSocket* sock = &UDPSocketList[i];
- if (sock->Backend) closesocket(sock->Backend);
+ delete RXBuffer;
+ RXBuffer = nullptr;
}
}
@@ -179,165 +276,6 @@ void FinishUDPFrame(u8* data, int len)
*(u16*)&udpheader[6] = htons(tmp);
}
-void FinishTCPFrame(u8* data, int len)
-{
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- // lengths
- *(u16*)&ipheader[2] = htons(len - 0xE);
-
- // IP checksum
- u32 tmp = 0;
-
- for (int i = 0; i < 20; i += 2)
- tmp += ntohs(*(u16*)&ipheader[i]);
- while (tmp >> 16)
- tmp = (tmp & 0xFFFF) + (tmp >> 16);
- tmp ^= 0xFFFF;
- *(u16*)&ipheader[10] = htons(tmp);
-
- u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14;
-
- // TCP checksum
- tmp = 0;
- tmp += ntohs(*(u16*)&ipheader[12]);
- tmp += ntohs(*(u16*)&ipheader[14]);
- tmp += ntohs(*(u16*)&ipheader[16]);
- tmp += ntohs(*(u16*)&ipheader[18]);
- tmp += ntohs(0x0600);
- tmp += tcplen;
- for (u8* i = tcpheader; i < &tcpheader[tcplen-1]; i += 2)
- tmp += ntohs(*(u16*)i);
- if (tcplen & 1)
- tmp += ntohs((u_short)tcpheader[tcplen-1]);
- while (tmp >> 16)
- tmp = (tmp & 0xFFFF) + (tmp >> 16);
- tmp ^= 0xFFFF;
- *(u16*)&tcpheader[16] = htons(tmp);
-}
-
-
-void HandleDHCPFrame(u8* data, int len)
-{
- u8 type = 0xFF;
-
- u32 transid = *(u32*)&data[0x2E];
-
- u8* options = &data[0x11A];
- for (;;)
- {
- if (options >= &data[len]) break;
- u8 opt = *options++;
- if (opt == 255) break;
-
- u8 len = *options++;
- switch (opt)
- {
- case 53: // frame type
- type = options[0];
- break;
- }
-
- options += len;
- }
-
- if (type == 0xFF)
- {
- printf("DHCP: bad frame\n");
- return;
- }
-
- printf("DHCP: frame type %d, transid %08X\n", type, transid);
-
- if (type == 1 || // discover
- type == 3) // request
- {
- u8 resp[512];
- u8* out = &resp[0];
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x11; // protocol (UDP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = htonl(kServerIP); out += 4; // source IP
- if (type == 1)
- {
- *(u32*)out = htonl(0xFFFFFFFF); out += 4; // destination IP
- }
- else if (type == 3)
- {
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
- }
-
- // UDP
- u8* udpheader = out;
- *(u16*)out = htons(67); out += 2; // source port
- *(u16*)out = htons(68); out += 2; // destination port
- *(u16*)out = 0; out += 2; // length
- *(u16*)out = 0; out += 2; // checksum
-
- // DHCP
- u8* body = out;
- *out++ = 0x02;
- *out++ = 0x01;
- *out++ = 0x06;
- *out++ = 0x00;
- *(u32*)out = transid; out += 4;
- *(u16*)out = 0; out += 2; // seconds elapsed
- *(u16*)out = 0; out += 2;
- *(u32*)out = htonl(0x00000000); out += 4; // client IP
- *(u32*)out = htonl(kClientIP); out += 4; // your IP
- *(u32*)out = htonl(kServerIP); out += 4; // server IP
- *(u32*)out = htonl(0x00000000); out += 4; // gateway IP
- memcpy(out, &data[6], 6); out += 6;
- memset(out, 0, 10); out += 10;
- memset(out, 0, 192); out += 192;
- *(u32*)out = 0x63538263; out += 4; // DHCP magic
-
- // DHCP options
- *out++ = 53; *out++ = 1;
- *out++ = (type==1) ? 2 : 5; // DHCP type: offer/ack
- *out++ = 1; *out++ = 4;
- *(u32*)out = htonl(0xFFFFFF00); out += 4; // subnet mask
- *out++ = 3; *out++ = 4;
- *(u32*)out = htonl(kServerIP); out += 4; // router
- *out++ = 51; *out++ = 4;
- *(u32*)out = htonl(442030); out += 4; // lease time
- *out++ = 54; *out++ = 4;
- *(u32*)out = htonl(kServerIP); out += 4; // DHCP server
- *out++ = 6; *out++ = 4;
- *(u32*)out = htonl(kDNSIP); out += 4; // DNS (hax)
-
- *out++ = 0xFF;
- memset(out, 0, 20); out += 20;
-
- u32 framelen = (u32)(out - &resp[0]);
- if (framelen & 1) { *out++ = 0; framelen++; }
- FinishUDPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
- }
-}
-
void HandleDNSFrame(u8* data, int len)
{
u8* ipheader = &data[0xE];
@@ -458,12 +396,13 @@ void HandleDNSFrame(u8* data, int len)
while (p)
{
struct sockaddr_in* addr = (struct sockaddr_in*)p->ai_addr;
- /*printf(" -> %d.%d.%d.%d",
- addr->sin_addr.S_un.S_un_b.s_b1, addr->sin_addr.S_un.S_un_b.s_b2,
- addr->sin_addr.S_un.S_un_b.s_b3, addr->sin_addr.S_un.S_un_b.s_b4);*/
-
- //addr_res = addr->sin_addr.S_un.S_addr;
addr_res = *(u32*)&addr->sin_addr;
+
+ printf(" -> %d.%d.%d.%d",
+ addr_res & 0xFF, (addr_res >> 8) & 0xFF,
+ (addr_res >> 16) & 0xFF, addr_res >> 24);
+
+ break;
p = p->ai_next;
}
}
@@ -490,653 +429,116 @@ void HandleDNSFrame(u8* data, int len)
if (framelen & 1) { *out++ = 0; framelen++; }
FinishUDPFrame(resp, framelen);
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
+ RXEnqueue(resp, framelen);
}
-void UDP_BuildIncomingFrame(UDPSocket* sock, u8* data, int len)
-{
- u8 resp[2048];
- u8* out = &resp[0];
-
- if (len > 1536) return;
-
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x11; // protocol (UDP)
- *(u16*)out = 0; out += 2; // checksum
- memcpy(out, sock->DestIP, 4); out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // UDP
- u8* resp_tcpheader = out;
- *(u16*)out = htons(sock->DestPort); out += 2; // source port
- *(u16*)out = htons(sock->SourcePort); out += 2; // destination port
- *(u16*)out = htons(len+8); out += 2; // length of header+data
- *(u16*)out = 0; out += 2; // checksum
-
- memcpy(out, data, len); out += len;
-
- u32 framelen = (u32)(out - &resp[0]);
- FinishUDPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-}
-
-void HandleUDPFrame(u8* data, int len)
+int SendPacket(u8* data, int len)
{
- u8* ipheader = &data[0xE];
- u8* udpheader = &data[0x22];
-
- // debug
- /*for (int j = 0; j < len; j += 16)
- {
- int rem = len - j;
- if (rem > 16) rem = 16;
- for (int i = 0; i < rem; i++)
- {
- printf("%02X ", data[i+j]);
- }
- printf("\n");
- }*/
-
- u16 srcport = ntohs(*(u16*)&udpheader[0]);
- u16 dstport = ntohs(*(u16*)&udpheader[2]);
+ if (!Ctx) return 0;
- int sockid = -1;
- UDPSocket* sock;
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (len > 2048)
{
- sock = &UDPSocketList[i];
- if (sock->Backend != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- sockid = i;
- break;
- }
+ printf("LAN_SendPacket: error: packet too long (%d)\n", len);
+ return 0;
}
- if (sockid == -1)
- {
- sockid = UDPSocketID;
- sock = &UDPSocketList[sockid];
-
- UDPSocketID++;
- if (UDPSocketID >= (sizeof(UDPSocketList)/sizeof(UDPSocket)))
- UDPSocketID = 0;
+ u16 ethertype = ntohs(*(u16*)&data[0xC]);
- if (sock->Backend != 0)
+ if (ethertype == 0x800)
+ {
+ u8 protocol = data[0x17];
+ if (protocol == 0x11) // UDP
{
- printf("LANMAGIC: closing previous UDP socket #%d\n", sockid);
- closesocket(sock->Backend);
+ u16 dstport = ntohs(*(u16*)&data[0x24]);
+ if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS
+ {
+ HandleDNSFrame(data, len);
+ return len;
+ }
}
-
- sock->Backend = socket(AF_INET, SOCK_DGRAM, 0);
-
- memcpy(sock->DestIP, &ipheader[16], 4);
- sock->SourcePort = srcport;
- sock->DestPort = dstport;
-
- memset(&sock->BackendAddr, 0, sizeof(sock->BackendAddr));
- sock->BackendAddr.sin_family = AF_INET;
- sock->BackendAddr.sin_port = htons(dstport);
- memcpy(&sock->BackendAddr.sin_addr, &ipheader[16], 4);
- /*if (bind(sock->Backend, (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr)) == -1)
- {
- printf("bind() shat itself :(\n");
- }*/
-
- printf("LANMAGIC: opening UDP socket #%d to %d.%d.%d.%d:%d, srcport %d\n",
- sockid,
- ipheader[16], ipheader[17], ipheader[18], ipheader[19],
- dstport, srcport);
}
- u16 udplen = ntohs(*(u16*)&udpheader[4]) - 8;
-
- printf("UDP: socket %d sending %d bytes\n", sockid, udplen);
- sendto(sock->Backend, (char*)&udpheader[8], udplen, 0,
- (struct sockaddr*)&sock->BackendAddr, sizeof(sock->BackendAddr));
-}
-
-void TCP_SYNACK(TCPSocket* sock, u8* data, int len)
-{
- u8 resp[128];
- u8* out = &resp[0];
-
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- u32 seqnum = htonl(*(u32*)&tcpheader[4]);
- seqnum++;
- sock->AckNum = seqnum;
-
- //printf("SYNACK SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum);
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = *(u32*)&ipheader[16]; out += 4; // source IP
- *(u32*)out = *(u32*)&ipheader[12]; out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = *(u16*)&tcpheader[2]; out += 2; // source port
- *(u16*)out = *(u16*)&tcpheader[0]; out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; sock->SeqNum++; // seq number
- *(u32*)out = htonl(seqnum); out += 4; // ack seq number
- *(u16*)out = htons(0x8012); out += 2; // flags (SYN+ACK)
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- // TCP options
- *out++ = 0x02; *out++ = 0x04; // max segment size
- *(u16*)out = htons(0x05B4); out += 2;
- *out++ = 0x01;
- *out++ = 0x01;
- *out++ = 0x04; *out++ = 0x02; // SACK permitted
- *out++ = 0x01;
- *out++ = 0x03; *out++ = 0x03; // window size
- *out++ = 0x08;
-
- u32 framelen = (u32)(out - &resp[0]);
- //if (framelen & 1) { *out++ = 0; framelen++; }
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-}
-
-void TCP_ACK(TCPSocket* sock, bool fin)
-{
- u8 resp[64];
- u8* out = &resp[0];
-
- u16 flags = 0x5010;
- if (fin) flags |= 0x0001;
-
- //printf("%sACK SEQ=%08X|%08X\n", fin?"FIN":" ", sock->SeqNum, sock->AckNum);
-
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- *(u32*)out = *(u32*)&sock->DestIP; out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = htonl(sock->DestPort); out += 2; // source port
- *(u16*)out = htonl(sock->SourcePort); out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number
- *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number
- *(u16*)out = htons(flags); out += 2; // flags
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- u32 framelen = (u32)(out - &resp[0]);
- //if (framelen & 1) { *out++ = 0; framelen++; }
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
+ slirp_input(Ctx, data, len);
+ return len;
}
-void TCP_BuildIncomingFrame(TCPSocket* sock, u8* data, int len)
-{
- u8 resp[2048];
- u8* out = &resp[0];
-
- if (len > 1536) return;
-//printf("INCOMING SEQ=%08X|%08X\n", sock->SeqNum, sock->AckNum);
- // ethernet
- memcpy(out, Wifi::GetMAC(), 6); out += 6; // hurf
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0800); out += 2;
-
- // IP
- u8* resp_ipheader = out;
- *out++ = 0x45;
- *out++ = 0x00;
- *(u16*)out = 0; out += 2; // total length
- *(u16*)out = htons(IPv4ID); out += 2; IPv4ID++;
- *out++ = 0x00;
- *out++ = 0x00;
- *out++ = 0x80; // TTL
- *out++ = 0x06; // protocol (TCP)
- *(u16*)out = 0; out += 2; // checksum
- memcpy(out, sock->DestIP, 4); out += 4; // source IP
- *(u32*)out = htonl(kClientIP); out += 4; // destination IP
-
- // TCP
- u8* resp_tcpheader = out;
- *(u16*)out = htons(sock->DestPort); out += 2; // source port
- *(u16*)out = htons(sock->SourcePort); out += 2; // destination port
- *(u32*)out = htonl(sock->SeqNum); out += 4; // seq number
- *(u32*)out = htonl(sock->AckNum); out += 4; // ack seq number
- *(u16*)out = htons(0x5018); out += 2; // flags (ACK, PSH)
- *(u16*)out = htons(0x7000); out += 2; // window size (uuuh)
- *(u16*)out = 0; out += 2; // checksum
- *(u16*)out = 0; out += 2; // urgent pointer
-
- memcpy(out, data, len); out += len;
-
- u32 framelen = (u32)(out - &resp[0]);
- FinishTCPFrame(resp, framelen);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
-
- sock->SeqNum += len;
-}
+const int PollListMax = 64;
+struct pollfd PollList[PollListMax];
+int PollListSize;
-void HandleTCPFrame(u8* data, int len)
+int SlirpCbAddPoll(int fd, int events, void* opaque)
{
- u8* ipheader = &data[0xE];
- u8* tcpheader = &data[0x22];
-
- u16 srcport = ntohs(*(u16*)&tcpheader[0]);
- u16 dstport = ntohs(*(u16*)&tcpheader[2]);
- u16 flags = ntohs(*(u16*)&tcpheader[12]);
-
- u32 tcpheaderlen = 4 * (flags >> 12);
- u32 tcplen = ntohs(*(u16*)&ipheader[2]) - 0x14;
- u32 tcpdatalen = tcplen - tcpheaderlen;
-
- /*printf("tcpflags=%04X header=%d data=%d seq=%08X|%08X\n",
- flags, tcpheaderlen, tcpdatalen,
- ntohl(*(u32*)&tcpheader[4]),
- ntohl(*(u32*)&tcpheader[8]));*/
-
- if (flags & 0x002) // SYN
+ if (PollListSize >= PollListMax)
{
- int sockid = -1;
- TCPSocket* sock;
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- printf("LANMAGIC: duplicate TCP socket\n");
- sockid = i;
- break;
- }
- }
-
- if (sockid == -1)
- {
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status == 0)
- {
- sockid = i;
- break;
- }
- }
- }
-
- if (sockid == -1)
- {
- printf("LANMAGIC: !! TCP SOCKET LIST FULL\n");
- return;
- }
-
- printf("LANMAGIC: opening TCP socket #%d to %d.%d.%d.%d:%d, srcport %d\n",
- sockid,
- ipheader[16], ipheader[17], ipheader[18], ipheader[19],
- dstport, srcport);
-
- // keep track of it
- sock->Status = 1;
- memcpy(sock->DestIP, &ipheader[16], 4);
- sock->DestPort = dstport;
- sock->SourcePort = srcport;
- sock->SeqNum = 0x13370000;
- sock->AckNum = 0;
-
- // open backend socket
- if (!sock->Backend)
- {
- sock->Backend = socket(AF_INET, SOCK_STREAM, 0);
- }
-
- struct sockaddr_in conn_addr;
- memset(&conn_addr, 0, sizeof(conn_addr));
- conn_addr.sin_family = AF_INET;
- memcpy(&conn_addr.sin_addr, &ipheader[16], 4);
- conn_addr.sin_port = htons(dstport);
- if (connect(sock->Backend, (sockaddr*)&conn_addr, sizeof(conn_addr)) == -1)
- {
- printf("connect() shat itself :(\n");
- }
- else
- {
- // acknowledge it
- TCP_SYNACK(sock, data, len);
- }
+ printf("slirp: POLL LIST FULL\n");
+ return -1;
}
- else
- {
- int sockid = -1;
- TCPSocket* sock;
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
- {
- sock = &TCPSocketList[i];
- if (sock->Status != 0 && !memcmp(&sock->DestIP, &ipheader[16], 4) &&
- sock->SourcePort == srcport && sock->DestPort == dstport)
- {
- sockid = i;
- break;
- }
- }
- if (sockid == -1)
- {
- printf("LANMAGIC: bad TCP packet\n");
- return;
- }
+ int idx = PollListSize++;
- // TODO: check those
- u32 seqnum = ntohl(*(u32*)&tcpheader[4]);
- u32 acknum = ntohl(*(u32*)&tcpheader[8]);
- sock->SeqNum = acknum;
- sock->AckNum = seqnum + tcpdatalen;
+ //printf("Slirp: add poll: fd=%d, idx=%d, events=%08X\n", fd, idx, events);
- // send data over the socket
- if (tcpdatalen > 0)
- {
- u8* tcpdata = &tcpheader[tcpheaderlen];
+ u16 evt = 0;
- printf("TCP: socket %d sending %d bytes (flags=%04X)\n", sockid, tcpdatalen, flags);
- send(sock->Backend, (char*)tcpdata, tcpdatalen, 0);
+ if (events & SLIRP_POLL_IN) evt |= POLLIN;
+ if (events & SLIRP_POLL_OUT) evt |= POLLWRNORM;
- // kind of a hack, there
- TCP_ACK(sock, false);
- }
+#ifndef __WIN32__
+ // CHECKME
+ if (events & SLIRP_POLL_PRI) evt |= POLLPRI;
+ if (events & SLIRP_POLL_ERR) evt |= POLLERR;
+ if (events & SLIRP_POLL_HUP) evt |= POLLHUP;
+#endif // !__WIN32__
- if (flags & 0x001) // FIN
- {
- // TODO: timeout etc
- printf("TCP: socket %d closing\n", sockid);
+ PollList[idx].fd = fd;
+ PollList[idx].events = evt;
- sock->Status = 0;
- closesocket(sock->Backend);
- sock->Backend = 0;
- }
- }
+ return idx;
}
-void HandleARPFrame(u8* data, int len)
+int SlirpCbGetREvents(int idx, void* opaque)
{
- u16 protocol = ntohs(*(u16*)&data[0x10]);
- if (protocol != 0x0800) return;
-
- u16 op = ntohs(*(u16*)&data[0x14]);
- u32 targetip = ntohl(*(u32*)&data[0x26]);
-
- // TODO: handle ARP to the client
- // this only handles ARP to the DHCP/router
-
- if (op == 1)
- {
- // opcode 1=req 2=reply
- // sender MAC
- // sender IP
- // target MAC
- // target IP
-
- const u8* targetmac;
- if (targetip == kServerIP) targetmac = kServerMAC;
- else if (targetip == kDNSIP) targetmac = kDNSMAC;
- else return;
-
- u8 resp[64];
- u8* out = &resp[0];
-
- // ethernet
- memcpy(out, &data[6], 6); out += 6;
- memcpy(out, kServerMAC, 6); out += 6;
- *(u16*)out = htons(0x0806); out += 2;
-
- // ARP
- *(u16*)out = htons(0x0001); out += 2; // hardware type
- *(u16*)out = htons(0x0800); out += 2; // protocol
- *out++ = 6; // MAC address size
- *out++ = 4; // IP address size
- *(u16*)out = htons(0x0002); out += 2; // opcode
- memcpy(out, targetmac, 6); out += 6;
- *(u32*)out = htonl(targetip); out += 4;
- memcpy(out, &data[0x16], 6+4); out += 6+4;
-
- u32 framelen = (u32)(out - &resp[0]);
-
- // TODO: if there is already a packet queued, this will overwrite it
- // that being said, this will only happen during DHCP setup, so probably
- // not a big deal
-
- PacketLen = framelen;
- memcpy(PacketBuffer, resp, PacketLen);
- RXNum = 1;
- }
- else
- {
- printf("wat??\n");
- }
-}
+ if (idx < 0 || idx >= PollListSize)
+ return 0;
-void HandlePacket(u8* data, int len)
-{
- u16 ethertype = ntohs(*(u16*)&data[0xC]);
+ //printf("Slirp: get revents, idx=%d, res=%04X\n", idx, FDList[idx].revents);
- if (ethertype == 0x0800) // IPv4
- {
- u8 protocol = data[0x17];
- if (protocol == 0x11) // UDP
- {
- u16 srcport = ntohs(*(u16*)&data[0x22]);
- u16 dstport = ntohs(*(u16*)&data[0x24]);
- if (srcport == 68 && dstport == 67) // DHCP
- {
- printf("LANMAGIC: DHCP packet\n");
- return HandleDHCPFrame(data, len);
- }
- else if (dstport == 53 && htonl(*(u32*)&data[0x1E]) == kDNSIP) // DNS
- {
- printf("LANMAGIC: DNS packet\n");
- return HandleDNSFrame(data, len);
- }
+ u16 evt = PollList[idx].revents;
+ int ret = 0;
- printf("LANMAGIC: UDP packet %d->%d\n", srcport, dstport);
- return HandleUDPFrame(data, len);
- }
- else if (protocol == 0x06) // TCP
- {
- printf("LANMAGIC: TCP packet\n");
- return HandleTCPFrame(data, len);
- }
- else
- printf("LANMAGIC: unsupported IP protocol %02X\n", protocol);
- }
- else if (ethertype == 0x0806) // ARP
- {
- printf("LANMAGIC: ARP packet\n");
- return HandleARPFrame(data, len);
- }
- else
- printf("LANMAGIC: unsupported ethernet type %04X\n", ethertype);
-}
+ if (evt & POLLIN) ret |= SLIRP_POLL_IN;
+ if (evt & POLLWRNORM) ret |= SLIRP_POLL_OUT;
+ if (evt & POLLPRI) ret |= SLIRP_POLL_PRI;
+ if (evt & POLLERR) ret |= SLIRP_POLL_ERR;
+ if (evt & POLLHUP) ret |= SLIRP_POLL_HUP;
-int SendPacket(u8* data, int len)
-{
- if (len > 2048)
- {
- printf("LAN_SendPacket: error: packet too long (%d)\n", len);
- return 0;
- }
-
- HandlePacket(data, len);
- return len;
+ return ret;
}
int RecvPacket(u8* data)
{
+ if (!Ctx) return 0;
+
int ret = 0;
- if (RXNum > 0)
- {
- memcpy(data, PacketBuffer, PacketLen);
- ret = PacketLen;
- RXNum = 0;
- }
- for (int i = 0; i < (sizeof(TCPSocketList)/sizeof(TCPSocket)); i++)
+ //if (PollListSize > 0)
{
- TCPSocket* sock = &TCPSocketList[i];
- if (sock->Status != 1) continue;
-
- fd_set fd;
- struct timeval tv;
-
- FD_ZERO(&fd);
- FD_SET(sock->Backend, &fd);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (!select(sock->Backend+1, &fd, 0, 0, &tv))
- {
- continue;
- }
-
- u8 recvbuf[1024];
- int recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0);
- if (recvlen < 1)
- {
- if (recvlen == 0)
- {
- // socket has closed from the other side
- printf("TCP: socket %d closed from other side\n", i);
- sock->Status = 2;
- TCP_ACK(sock, true);
- }
- continue;
- }
-
- printf("TCP: socket %d receiving %d bytes\n", i, recvlen);
- TCP_BuildIncomingFrame(sock, recvbuf, recvlen);
-
- // debug
- /*for (int j = 0; j < recvlen; j += 16)
- {
- int rem = recvlen - j;
- if (rem > 16) rem = 16;
- for (int k = 0; k < rem; k++)
- {
- printf("%02X ", recvbuf[k+j]);
- }
- printf("\n");
- }*/
-
- //recvlen = recv(sock->Backend, (char*)recvbuf, 1024, 0);
- //if (recvlen == 0) printf("it closed immediately after\n");
+ u32 timeout = 0;
+ PollListSize = 0;
+ slirp_pollfds_fill(Ctx, &timeout, SlirpCbAddPoll, nullptr);
+ int res = poll(PollList, PollListSize, timeout);
+ slirp_pollfds_poll(Ctx, res<0, SlirpCbGetREvents, nullptr);
}
- for (int i = 0; i < (sizeof(UDPSocketList)/sizeof(UDPSocket)); i++)
+ if (!RXBuffer->IsEmpty())
{
- UDPSocket* sock = &UDPSocketList[i];
- if (sock->Backend == 0) continue;
-
- fd_set fd;
- struct timeval tv;
-
- FD_ZERO(&fd);
- FD_SET(sock->Backend, &fd);
- tv.tv_sec = 0;
- tv.tv_usec = 0;
-
- if (!select(sock->Backend+1, &fd, 0, 0, &tv))
- {
- continue;
- }
-
- u8 recvbuf[1024];
- sockaddr_t fromAddr;
- socklen_t fromLen = sizeof(sockaddr_t);
- int recvlen = recvfrom(sock->Backend, (char*)recvbuf, 1024, 0, &fromAddr, &fromLen);
- if (recvlen < 1) continue;
+ u32 header = RXBuffer->Read();
+ u32 len = header & 0xFFFF;
- if (fromAddr.sa_family != AF_INET) continue;
- struct sockaddr_in* fromAddrIn = (struct sockaddr_in*)&fromAddr;
- if (memcmp(&fromAddrIn->sin_addr, sock->DestIP, 4)) continue;
- if (ntohs(fromAddrIn->sin_port) != sock->DestPort) continue;
+ for (int i = 0; i < len; i += 4)
+ ((u32*)data)[i>>2] = RXBuffer->Read();
- printf("UDP: socket %d receiving %d bytes\n", i, recvlen);
- UDP_BuildIncomingFrame(sock, recvbuf, recvlen);
+ ret = header >> 16;
}
return ret;
diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp
index de6887c..47b3490 100644
--- a/src/frontend/qt_sdl/main.cpp
+++ b/src/frontend/qt_sdl/main.cpp
@@ -1285,6 +1285,8 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
{
if (event->isAutoRepeat()) return;
+ if (event->key() == Qt::Key_F11) NDS::debug(0);
+
Input::KeyPress(event);
}
@@ -2083,12 +2085,12 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho
if (argv_w) LocalFree(argv_w);
- if (AttachConsole(ATTACH_PARENT_PROCESS))
+ /*if (AttachConsole(ATTACH_PARENT_PROCESS))
{
freopen("CONOUT$", "w", stdout);
freopen("CONOUT$", "w", stderr);
printf("\n");
- }
+ }*/
int ret = main(argc, argv);