From ab15d7402a38946d18cbdc909274f438e7e752c2 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Thu, 18 Aug 2022 19:47:01 +0200 Subject: [PATCH] attempt at betterer wifi * add preliminary sync mechanism * fix gaps in wifi implementation --- src/ARM.cpp | 16 +- src/NDS.cpp | 19 +- src/Platform.h | 3 + src/Wifi.cpp | 572 ++++++++++++++++++++++++++++--- src/frontend/qt_sdl/Platform.cpp | 355 +++++++++++++++---- src/frontend/qt_sdl/main.cpp | 24 +- src/frontend/qt_sdl/main.h | 2 + 7 files changed, 864 insertions(+), 127 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index e19cb002..66fe5130 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -42,8 +42,6 @@ // // MUL/MLA seems to take 1I on ARM9 - - u32 ARM::ConditionTable[16] = { 0xF0F0, // EQ @@ -770,6 +768,20 @@ void ARMv4::Execute() AddCycles_C(); } + //if (R[15]==0x02300ECE) printf("PISSBOURF: %08X\n", R[0]); + // R7=3807D20 + /*if (R[15]==0x02301172 && (R[0]&0x2800)==0x2800) + { + printf("SENSE. %08X\n", R[7]); + for (int i = 0; i < 16; i++) printf("%02X ", NDS::ARM7Read8(R[7]+i)); + for (int i = 0; i < 16; i++) printf("%02X ", NDS::ARM7Read8(R[7]+0x10+i)); + for (int i = 0; i < 16; i++) printf("%02X ", NDS::ARM7Read8(R[7]+0x20+i)); + for (int i = 0; i < 16; i++) printf("%02X ", NDS::ARM7Read8(R[7]+0x30+i)); + printf("\n"); + }*/ + // printf("FENETRE. %04X, %08X\n", R[0], R[7]); + //if (R[15]==0x0230CEFE) printf("SET SHITTY PACKET FLAGS %04X (%04X/%04X)\n", R[3], NDS::ARM7Read16(0x04808094), NDS::ARM7Read16(0x04808098)); + // TODO optimize this shit!!! if (Halted) { diff --git a/src/NDS.cpp b/src/NDS.cpp index 2ff8ffe2..9cfcad60 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1941,8 +1941,8 @@ void debug(u32 param) //for (int i = 0; i < 9; i++) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); - /*FILE* - shit = fopen("debug/construct.bin", "wb"); + FILE* + shit = fopen("debug/pictochat.bin", "wb"); fwrite(ARM9->ITCM, 0x8000, 1, shit); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { @@ -1954,9 +1954,9 @@ void debug(u32 param) u32 val = ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit);*/ + fclose(shit); - FILE* + /*FILE* shit = fopen("debug/directboot9.bin", "wb"); for (u32 i = 0x02000000; i < 0x04000000; i+=4) { @@ -1970,7 +1970,7 @@ void debug(u32 param) u32 val = DSi::ARM7Read32(i); fwrite(&val, 4, 1, shit); } - fclose(shit); + fclose(shit);*/ } @@ -2425,6 +2425,15 @@ u8 ARM7Read8(u32 addr) u16 ARM7Read16(u32 addr) { + /*if (addr == (0x03807D38+0x28)) + { + if (ARM7Read16(0x03807D38+0xC)==0x228) + printf("!!!! READING PISSY HEADER %08X\n", NDS::GetPC(1)); + }*/ + /*if ((!(addr&0x10000000)) && (addr<0x04000000)) + if (ARM7Read16(0x10000000|(addr-0x1C))==0x228) + printf("!!!! READING PISSY HEADER %08X\n", NDS::GetPC(1)); + if(addr&0x10000000) addr&=0x0FFFFFFF;*/ if (addr < 0x00004000) { if (ARM7->R[15] >= 0x00004000) diff --git a/src/Platform.h b/src/Platform.h index 4106977b..31b421f3 100644 --- a/src/Platform.h +++ b/src/Platform.h @@ -158,6 +158,9 @@ bool MP_Init(); void MP_DeInit(); int MP_SendPacket(u8* data, int len); int MP_RecvPacket(u8* data, bool block); +bool MP_SendSync(u16 clientmask, u16 type, u64 val); +bool MP_WaitSync(u16 clientmask, u16* type, u64* val); +u16 MP_WaitMultipleSyncs(u16 type, u16 clientmask, u64 curval); // LAN comm interface // packet type: Ethernet (802.3) diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 4e3bc17d..a678b61f 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -25,13 +25,15 @@ #include "Platform.h" #include "ARM.h" #include "GPU.h" - +u16 zanf = 2423; namespace Wifi { //#define WIFI_LOG printf #define WIFI_LOG(...) {} +#define PRINT_MAC(pf, mac) printf("%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]; @@ -58,6 +60,7 @@ u32 RFRegs[0x40]; struct TXSlot { + bool Valid; u16 Addr; u16 Length; u8 Rate; @@ -80,6 +83,10 @@ u32 RXCounter; int MPReplyTimer; int MPNumReplies; +int MPReplyFrame; // for client +u8 MPHostMAC[6]; +u8 MPHostBSS[6]; +u16 MPHostSeqNo; bool MPInited; bool LANInited; @@ -87,6 +94,13 @@ bool LANInited; int USUntilPowerOn; bool ForcePowerOn; +// MULTIPLAYER SYNC APPARATUS +bool IsMPClient; +u64 TimeOffsetToHost; // clienttime - hosttime +u64 NextSync; // for clients: timestamp for next forced sync +bool SyncBack; // for clients: whether to send the host a sync once the sync is reached +const u64 kMaxRunahead = 4096; + // multiplayer host TX sequence: // 1. preamble // 2. IRQ7 @@ -204,15 +218,25 @@ void Reset() USCompare = 0; BlockBeaconIRQ14 = false; + memset(TXSlots, 0, sizeof(TXSlots)); ComStatus = 0; TXCurSlot = -1; RXCounter = 0; MPReplyTimer = 0; MPNumReplies = 0; + MPReplyFrame = 0; + memset(MPHostMAC, 0, 6); + memset(MPHostBSS, 0, 6); + MPHostSeqNo = 0; CmdCounter = 0; + IsMPClient = false; + TimeOffsetToHost = 0; + NextSync = 0; + SyncBack = false; + WifiAP::Reset(); } @@ -318,7 +342,7 @@ void SetIRQ15() void SetStatus(u32 status) { - // TODO, eventually: states 2/4, also find out what state 7 is + // TODO, eventually: states 2/4/7 u16 rfpins[10] = {0x04, 0x84, 0, 0x46, 0, 0x84, 0x87, 0, 0x46, 0x04}; IOPORT(W_RFStatus) = status; IOPORT(W_RFPins) = rfpins[status]; @@ -331,8 +355,6 @@ bool MACEqual(u8* a, u8* b) } -// TODO: set RFSTATUS/RFPINS - int PreambleLen(int rate) { if (rate == 1) return 192; @@ -340,6 +362,16 @@ int PreambleLen(int rate) return 192; } +u32 NumClients(u16 bitmask) +{ + u32 ret = 0; + for (int i = 1; i < 16; i++) + { + if (bitmask & (1<Addr + 0x4]; @@ -371,7 +403,7 @@ void StartTX_Cmd() // TODO: cancel the transfer if there isn't enough time left (check CMDCOUNT) - if (IOPORT(W_TXSlotCmd) & 0x7000) printf("wifi: !! unusual TXSLOT_CMD bits set %04X\n", IOPORT(W_TXSlotCmd)); + if (IOPORT(W_TXSlotCmd) & 0x7000) printf("wifi: !! unusual TXSLOT_CMD bits set %04X %08X\n", IOPORT(W_TXSlotCmd), NDS::GetPC(1)); slot->Addr = (IOPORT(W_TXSlotCmd) & 0x0FFF) << 1; slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF; @@ -442,25 +474,60 @@ void FireTX() return; } } +u16 vogon = 0x1312; void SendMPReply(u16 clienttime, u16 clientmask) { TXSlot* slot = &TXSlots[5]; + vogon = *(u16*)&RXBuffer[0xC + 22]; // seqno + // mark the last packet as success. dunno what the MSB is, it changes. + //if (slot->Valid) if (IOPORT(W_TXSlotReply2) & 0x8000) *(u16*)&RAM[slot->Addr] = 0x0001; + // CHECKME!! + // can the transfer rate for MP replies be set, or is it determined from the CMD transfer rate? + // how does it work for default empty replies? + slot->Rate = 2; + IOPORT(W_TXSlotReply2) = IOPORT(W_TXSlotReply1); IOPORT(W_TXSlotReply1) = 0; +//printf("SENDING MP REPLY: %04X/%04X, PORTS=%04X/%04X\n", clienttime, clientmask, IOPORT(W_TXSlotReply1), IOPORT(W_TXSlotReply2)); + if (!(IOPORT(W_TXSlotReply2) & 0x8000)) + { + slot->Valid = false; + } + else + { + slot->Valid = true; + + slot->Addr = (IOPORT(W_TXSlotReply2) & 0x0FFF) << 1; + slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF; + + // the packet is entirely ignored if it lasts longer than the maximum reply time + u32 duration = PreambleLen(slot->Rate) + (slot->Length * (slot->Rate==2 ? 4:8)); + if (duration > clienttime) + slot->Valid = false; + + //printf("SENDING MP REPLY %04X, %d\n", slot->Addr, slot->Valid); + // replies: 0000/0234 + // 04804000 / 04804234 + } // this seems to be set upon IRQ0 // TODO: how does it behave if the packet addr is changed before it gets sent? (maybe just not possible) - if (IOPORT(W_TXSlotReply2) & 0x8000) + if (slot->Valid) { - slot->Addr = (IOPORT(W_TXSlotReply2) & 0x0FFF) << 1; //*(u16*)&RAM[slot->Addr + 0x4] = 0x0001; IncrementTXCount(slot); + + slot->CurPhase = 0; + } + else + { + slot->CurPhase = 10; } u16 clientnum = 0; @@ -470,8 +537,20 @@ void SendMPReply(u16 clienttime, u16 clientmask) clientnum++; } - slot->CurPhase = 0; - slot->CurPhaseTime = 16 + ((clienttime + 10) * clientnum); + slot->CurPhaseTime = 16 + ((clienttime + 10) * clientnum) + PreambleLen(slot->Rate); + + MPReplyFrame = 112 + ((clienttime + 10) * NumClients(clientmask)); + MPReplyFrame -= slot->CurPhaseTime; // count the time from the reply to the ack + + IOPORT(W_TXBusy) |= 0x0080; +} + +void DummyMPReplyFrame(u16 clienttime, u16 clientmask) +{ + TXSlot* slot = &TXSlots[5]; + + slot->CurPhase = 5; + slot->CurPhaseTime = 112 + ((clienttime + 10) * NumClients(clientmask)); IOPORT(W_TXBusy) |= 0x0080; } @@ -488,6 +567,8 @@ void SendMPDefaultReply() // TODO reply[0x8] = 0x14; + *(u16*)&reply[0x6] = vogon; + *(u16*)&reply[0xC + 0x00] = 0x0158; *(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO?? *(u16*)&reply[0xC + 0x04] = IOPORT(W_BSSID0); @@ -529,21 +610,42 @@ void SendMPAck() *(u16*)&ack[0xC + 0x14] = IOPORT(W_MACAddr2); *(u16*)&ack[0xC + 0x16] = IOPORT(W_TXSeqNo) << 4; *(u16*)&ack[0xC + 0x18] = 0x0033; // ??? - *(u16*)&ack[0xC + 0x1A] = 0; + *(u16*)&ack[0xC + 0x1A] = 0; // TODO: bitmask of which clients failed to reply *(u32*)&ack[0xC + 0x1C] = 0; int txlen = Platform::MP_SendPacket(ack, 12+32); WIFI_LOG("wifi: sent %d/44 bytes of MP ack, %d %d\n", txlen, ComStatus, RXTime); } -u32 NumClients(u16 bitmask) +bool FakeRX(); + +void FakeMPAck() { - u32 ret = 0; - for (int i = 1; i < 16; i++) - { - if (bitmask & (1<Length==34) + { + u32 len = *(u16*)&RXBuffer[8]; + len += 12; + /*printf("REPLY: %d bytes\n", len); + for (int y = 0; y < len; y+=16) + { + printf("%04X: ", y); + int linelen = 16; + if ((y+linelen) > len) linelen = len - y; + for (int x = 0; x < linelen; x++) + { + printf(" %02X", RXBuffer[y+x]); + } + printf("\n"); + } + printf("--------------\n");*/ + } } + else printf("[HOST] failed to receive reply :(\n"); // TODO: properly handle reply errors // also, if the reply is too big to fit within its window, what happens? @@ -592,31 +714,16 @@ bool ProcessTX(TXSlot* slot, int num) SetStatus(8); - // if no reply is configured, send a default empty reply - if (!(IOPORT(W_TXSlotReply2) & 0x8000)) - { - SendMPDefaultReply(); + //slot->Addr = (IOPORT(W_TXSlotReply2) & 0x0FFF) << 1; + //slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF; - slot->Addr = 0; - slot->Length = 28; - slot->Rate = 2; // TODO - slot->CurPhase = 4; - slot->CurPhaseTime = 28*4; - slot->HalfwordTimeMask = 0xFFFFFFFF; - IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; - break; - } - - slot->Addr = (IOPORT(W_TXSlotReply2) & 0x0FFF) << 1; - slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF; + /*u8 rate = RAM[slot->Addr + 0x8]; + if (rate == 0x14) slot->Rate = 2; + else slot->Rate = 1;*/ // TODO: duration should be set by hardware // doesn't seem to be important //RAM[slot->Addr + 0xC + 2] = 0x00F0; - - u8 rate = RAM[slot->Addr + 0x8]; - if (rate == 0x14) slot->Rate = 2; - else slot->Rate = 1; } else SetStatus(3); @@ -644,10 +751,27 @@ bool ProcessTX(TXSlot* slot, int num) *(u64*)&RAM[slot->Addr + 0xC + 24] = USCounter; } - //u32 noseqno = 0; - //if (num == 1) noseqno = (IOPORT(W_TXSlotCmd) & 0x4000); + /*if (slot->Length==34) + { + printf("CMD: %d bytes, %04X\n", slot->Length+12, IOPORT(W_TXSlotCmd)); + for (int y = 0; y < slot->Length+12; y+=16) + { + printf("%04X: ", y); + int linelen = 16; + if ((y+linelen) > (slot->Length+12)) linelen = (slot->Length+12) - y; + for (int x = 0; x < linelen; x++) + { + printf(" %02X", RAM[slot->Addr+y+x]); + } + printf("\n"); + } + printf("--------------\n"); + }*/ - //if (!noseqno) + u32 noseqno = 0; + if (num == 1) noseqno = (IOPORT(W_TXSlotCmd) & 0x4000); + + if (!noseqno) { *(u16*)&RAM[slot->Addr + 0xC + 22] = IOPORT(W_TXSeqNo) << 4; IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; @@ -656,16 +780,75 @@ bool ProcessTX(TXSlot* slot, int num) // set TX addr IOPORT(W_RXTXAddr) = slot->Addr >> 1; - // send - int txlen = Platform::MP_SendPacket(&RAM[slot->Addr], 12 + slot->Length); - WIFI_LOG("wifi: sent %d/%d bytes of slot%d packet, addr=%04X, framectl=%04X, %04X %04X\n", - txlen, slot->Length+12, num, slot->Addr, *(u16*)&RAM[slot->Addr + 0xC], - *(u16*)&RAM[slot->Addr + 0x24], *(u16*)&RAM[slot->Addr + 0x26]); + if (num == 1) + { + // make sure the clients are synced up + // TODO!!!! this should be for all currently connected clients regardless of the clientmask in the packet + u16 clientmask = *(u16*)&RAM[slot->Addr + 0xC + 26]; + Platform::MP_SendSync(/*clientmask*/0x0002, 2, USCounter); + //printf("[HOST] sending CMD, sent sync2, waiting\n"); + u16 res = Platform::MP_WaitMultipleSyncs(3, /*clientmask*/0x0002, USCounter); + //printf("[HOST] got sync3: %04X\n", res); + + //if (slot->Length < 100) + //if (*(u16*)&RAM[slot->Addr+0x28] == 0) + // *(u16*)&RAM[slot->Addr+0x28] = 0x0100; + + // send + int txlen = Platform::MP_SendPacket(&RAM[slot->Addr], 12 + slot->Length); + WIFI_LOG("wifi: sent %d/%d bytes of slot%d packet, addr=%04X, framectl=%04X, %04X %04X\n", + txlen, slot->Length+12, num, slot->Addr, *(u16*)&RAM[slot->Addr + 0xC], + *(u16*)&RAM[slot->Addr + 0x24], *(u16*)&RAM[slot->Addr + 0x26]); +//if (IOPORT(W_TXSlotCmd) & 0x4000) + + // send further sync + u32 numclients = NumClients(clientmask); + u32 replywait = 112 + ((10 + IOPORT(W_CmdReplyTime)) * numclients); + u32 acklen = 32 * (slot->Rate==2 ? 4:8); + //Platform::MP_SendSync(/*clientmask*/0x0002, 1, USCounter + len + replywait + acklen);// + kMaxRunahead); + Platform::MP_SendSync(/*clientmask*/0x0002, 2, USCounter + len + replywait); + } + else if (num == 5) + { + u16 barfo = *(u16*)&RAM[slot->Addr+6]; + *(u16*)&RAM[slot->Addr+6] = vogon; + + // send + int txlen = Platform::MP_SendPacket(&RAM[slot->Addr], 12 + slot->Length); + WIFI_LOG("wifi: sent %d/%d bytes of slot%d packet, addr=%04X, framectl=%04X, %04X %04X\n", + txlen, slot->Length+12, num, slot->Addr, *(u16*)&RAM[slot->Addr + 0xC], + *(u16*)&RAM[slot->Addr + 0x24], *(u16*)&RAM[slot->Addr + 0x26]); + + *(u16*)&RAM[slot->Addr+6] = barfo; + } + else //if (num != 5) + { + // send + int txlen = Platform::MP_SendPacket(&RAM[slot->Addr], 12 + slot->Length); + WIFI_LOG("wifi: sent %d/%d bytes of slot%d packet, addr=%04X, framectl=%04X, %04X %04X\n", + txlen, slot->Length+12, num, slot->Addr, *(u16*)&RAM[slot->Addr + 0xC], + *(u16*)&RAM[slot->Addr + 0x24], *(u16*)&RAM[slot->Addr + 0x26]); + } // if the packet is being sent via LOC1..3, send it to the AP // any packet sent via CMD/REPLY/BEACON isn't going to have much use outside of local MP if (num == 0 || num == 2 || num == 3) + { + u16 framectl = *(u16*)&RAM[slot->Addr + 0xC]; + if ((framectl & 0x00FF) == 0x0010) + { + // if we're sending an association response: + // we are likely acting as a local MP host, and are welcoming a new client to the club + // in this case, sync them up: send them our current USCOUNT value + // which will let them understand further sync values + + u16 aid = *(u16*)&RAM[slot->Addr + 0xC + 24 + 4]; + //printf("[HOST] syncing client %04X, sync=%016llX\n", aid, USCounter); + Platform::MP_SendSync(1<<(aid&0xF), 0, USCounter); + } + WifiAP::SendPacket(&RAM[slot->Addr], 12 + slot->Length); + } if (num == 4) { @@ -674,6 +857,21 @@ bool ProcessTX(TXSlot* slot, int num) } break; + case 10: // preamble done (default empty MP reply) + { + SetIRQ(7); + SetStatus(8); + + SendMPDefaultReply(); + + //slot->Addr = 0; + //slot->Length = 28; + slot->CurPhase = 4; + slot->CurPhaseTime = 28*4; + slot->HalfwordTimeMask = 0xFFFFFFFF; + } + break; + case 1: // transmit done { // for the MP reply slot, this is set later @@ -692,8 +890,10 @@ bool ProcessTX(TXSlot* slot, int num) u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; MPNumReplies = NumClients(clientmask); - MPReplyTimer = 16; + MPReplyTimer = 16 + PreambleLen(slot->Rate); + // TODO: 112 likely includes the ack preamble, which needs adjusted + // for long-preamble settings slot->CurPhase = 2; slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * MPNumReplies); @@ -711,6 +911,11 @@ bool ProcessTX(TXSlot* slot, int num) IOPORT(W_TXBusy) &= ~0x80; FireTX(); return true; + + /*slot->CurPhase = 5; + slot->CurPhaseTime = MPReplyFrame; + + break;*/ } IOPORT(W_TXBusy) &= ~(1<Rate == 2) slot->CurPhaseTime = 32 * 4; else slot->CurPhaseTime = 32 * 8; + //SendMPAck(); + /*printf("HOST MP ACK:\n"); + PRINT_MAC("-MAC: ", (u8*)&IOPORT(W_MACAddr0)); + PRINT_MAC("-BSS: ", (u8*)&IOPORT(W_BSSID0)); + printf("-SeqNo: %04X\n", IOPORT(W_TXSeqNo)<<4);*/ + + // make sure the clients are synced up + // TODO!!!! this should be for all currently connected clients regardless of the clientmask in the packet + u16 clientmask = *(u16*)&RAM[slot->Addr + 0xC + 26]; + //Platform::MP_SendSync(/*clientmask*/0x0002, 2, USCounter); + //printf("[HOST] sending CMD, sent sync2, waiting\n"); + u16 res = Platform::MP_WaitMultipleSyncs(3, /*clientmask*/0x0002, USCounter); + //printf("[HOST] got sync3: %04X\n", res); + + // send SendMPAck(); + // send further sync + Platform::MP_SendSync(/*clientmask*/0x0002, 1, USCounter + slot->CurPhaseTime); + slot->CurPhase = 3; } break; @@ -767,7 +990,11 @@ bool ProcessTX(TXSlot* slot, int num) IncrementTXCount(slot); SetIRQ(12); - IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; + + //if (!(IOPORT(W_TXSlotCmd) & 0x4000)) + { + IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; + } if (IOPORT(W_TXStatCnt) & 0x2000) { @@ -776,17 +1003,37 @@ bool ProcessTX(TXSlot* slot, int num) } SetStatus(1); + // let clients run ahead some + u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; + //Platform::MP_SendSync(clientmask, 1, kMaxRunahead); + FireTX(); } return true; case 4: // MP default reply transfer finished { + IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; + IOPORT(W_TXBusy) &= ~0x80; SetStatus(1); FireTX(); } return true; + + case 5: // MP reply frame finished (client side) + { + IOPORT(W_TXBusy) &= ~0x80; + //SetStatus(1); + + //printf("[%016llX] CLIENT: ACK TIME\n", USCounter); + FakeMPAck(); + + /*slot->CurPhase = 4; + // CHECKME + if (slot->Rate == 2) slot->CurPhaseTime = 32 * 4; + else slot->CurPhaseTime = 32 * 8;*/ + } } return false; @@ -803,7 +1050,7 @@ inline void IncrementRXAddr(u16& addr, u16 inc = 2) addr = (IOPORT(W_RXBufBegin) & 0x1FFE); } } - +u16 zarp = 0; bool CheckRX(bool block) { if (!(IOPORT(W_RXCnt) & 0x8000)) @@ -894,6 +1141,12 @@ bool CheckRX(bool block) !(RXBuffer[12 + a_dst] & 0x01)) { printf("received packet %04X but it didn't pass the MAC check\n", framectl); + printf("DST: %02X:%02X:%02X:%02X:%02X:%02X\n", + RXBuffer[12 + a_dst + 0], RXBuffer[12 + a_dst + 1], RXBuffer[12 + a_dst + 2], + RXBuffer[12 + a_dst + 3], RXBuffer[12 + a_dst + 4], RXBuffer[12 + a_dst + 5]); + printf("BSS: %02X:%02X:%02X:%02X:%02X:%02X\n", + RXBuffer[12 + a_bss + 0], RXBuffer[12 + a_bss + 1], RXBuffer[12 + a_bss + 2], + RXBuffer[12 + a_bss + 3], RXBuffer[12 + a_bss + 4], RXBuffer[12 + a_bss + 5]); continue; } @@ -902,6 +1155,155 @@ bool CheckRX(bool block) WIFI_LOG("wifi: received packet FC:%04X SN:%04X CL:%04X RXT:%d CMT:%d\n", framectl, *(u16*)&RXBuffer[12+4+6+6+6], *(u16*)&RXBuffer[12+4+6+6+6+2+2], framelen*4, IOPORT(W_CmdReplyTime)); +//if (framectl==0x0228) printf("RX CMD: len=%d, client=%04X, rxfilter=%04X/%04X\n", + // framelen, *(u16*)&RXBuffer[12+4+6+6+6+2+2], IOPORT(W_RXFilter), IOPORT(W_RXFilter2)); + //if (framectl==0x0228 && zarp==0x0228) printf("[CLIENT] failed to receive ack\n"); + //if (framectl==0x0218 && zarp==0x0218) printf("[CLIENT] failed to receive cmd\n"); + //if (framectl==0x0218) printf("[%016llX] CLIENT: ACK RECEIVED\n", USCounter); + zarp = framectl; + + if (block && (framectl == 0x0118 || framectl == 0x0158)) + { + u16 bourf = (IOPORT(W_TXSeqNo) - 0x1) << 4; + if (bourf != *(u16*)&RXBuffer[6]) + printf("BAD REPLY SEQNO!!! SENT %04X, RECV %04X\n", bourf, *(u16*)&RXBuffer[6]); + } + + // if receiving an association response: get the sync value from the host + // TODO only do this for local multiplayer and not online mode!!!!!!!! + if ((framectl & 0x00FF) == 0x0010) + { + u16 aid = *(u16*)&RXBuffer[12+24+4]; + + //u64 sync = Platform::MP_WaitSync(0, 1<<(aid&0xF), 0); + u64 sync = 0; + for (;;) + { + u16 type; u64 val; + bool res = Platform::MP_WaitSync(1<<(aid&0xF), &type, &val); + if (!res) break; + if (type != 0) continue; + sync = val; + break; + } + if (sync) + { + printf("[CLIENT %01X] host sync=%016llX\n", aid&0xF, sync); + + IsMPClient = true; + TimeOffsetToHost = USCounter - sync; + NextSync = USCounter + kMaxRunahead; + } + } + + // make RX header + + if (bssidmatch) rxflags |= 0x8000; + + *(u16*)&RXBuffer[0] = rxflags; + *(u16*)&RXBuffer[2] = 0x0040; // ??? + *(u16*)&RXBuffer[6] = txrate; + *(u16*)&RXBuffer[8] = framelen; + *(u16*)&RXBuffer[10] = 0x4080; // min/max RSSI. dunno + + RXTime = framelen; + + if (txrate == 0x14) + { + RXTime *= 4; + RXHalfwordTimeMask = 0x7; + } + else + { + RXTime *= 8; + RXHalfwordTimeMask = 0xF; + } + + u16 addr = IOPORT(W_RXBufWriteCursor) << 1; + IncrementRXAddr(addr, 12); + IOPORT(W_RXTXAddr) = addr >> 1; + + RXBufferPtr = 12; + + SetIRQ(6); + SetStatus(6); + return true; +} + +// FIXME!!! SUPER UGLY COPYPASTA +bool FakeRX() +{ + if (!(IOPORT(W_RXCnt) & 0x8000)) + return false; + + if (IOPORT(W_RXBufBegin) == IOPORT(W_RXBufEnd)) + return false; + + u16 framelen; + u16 framectl; + u8 txrate; + bool bssidmatch; + u16 rxflags; + + framelen = *(u16*)&RXBuffer[10]; + framelen -= 4; + + framectl = *(u16*)&RXBuffer[12+0]; + txrate = RXBuffer[8]; + + u32 a_src, a_dst, a_bss; + rxflags = 0x0010; + switch (framectl & 0x000C) + { + case 0x0000: // management + a_src = 10; + a_dst = 4; + a_bss = 16; + if ((framectl & 0x00F0) == 0x0080) + rxflags |= 0x0001; + break; + + case 0x0004: // control + printf("blarg\n"); + return false; + + case 0x0008: // data + switch (framectl & 0x0300) + { + case 0x0000: // STA to STA + a_src = 10; + a_dst = 4; + a_bss = 16; + break; + case 0x0100: // STA to DS + a_src = 10; + a_dst = 16; + a_bss = 4; + break; + case 0x0200: // DS to STA + a_src = 16; + a_dst = 4; + a_bss = 10; + break; + case 0x0300: // DS to DS + printf("blarg\n"); + return false; + } + // TODO: those also trigger on other framectl values + // like 0208 -> C + framectl &= 0xE7FF; + if (framectl == 0x0228) rxflags |= 0x000C; // MP host frame + else if (framectl == 0x0218) rxflags |= 0x000D; // MP ack frame + else if (framectl == 0x0118) rxflags |= 0x000E; // MP reply frame + else if (framectl == 0x0158) rxflags |= 0x000F; // empty MP reply frame + else rxflags |= 0x0008; + break; + } + + bssidmatch = MACEqual(&RXBuffer[12 + a_bss], (u8*)&IOPORT(W_BSSID0)); + + WIFI_LOG("wifi: received fake packet FC:%04X SN:%04X CL:%04X RXT:%d CMT:%d\n", + framectl, *(u16*)&RXBuffer[12+4+6+6+6], *(u16*)&RXBuffer[12+4+6+6+6+2+2], framelen*4, IOPORT(W_CmdReplyTime)); // make RX header @@ -993,6 +1395,51 @@ void USTimer(u32 param) } if (!uspart) MSTimer(); + + if (USCounter == NextSync) + { + if (SyncBack) + {//printf("[CLIENT %01X] sending sync3\n", IOPORT(W_AIDLow)); + SyncBack = false; + u16 aid = IOPORT(W_AIDLow); + Platform::MP_SendSync(1<<(aid&0xF), 3, 0); + + if (CheckRX(true)) + { + ComStatus |= 0x1; + } + } + + //u64 sync = Platform::MP_WaitSync(1, 1<<(IOPORT(W_AIDLow)&0xF), USCounter - TimeOffsetToHost); + for (;;) + { + u16 type; u64 val; + u16 aid = IOPORT(W_AIDLow); + //printf("[CLIENT %01X] waiting for sync\n", aid); + bool res = Platform::MP_WaitSync(1<<(aid&0xF), &type, &val); + //printf("[CLIENT %01X] got sync, res=%d type=%04X val=%016llX\n", aid, res, type, val); + if (!res) break; + + // timeoffset = client - host + val += TimeOffsetToHost; + + if ((type == 1) && (val > USCounter)) + { + NextSync = val; + break; + } + else if ((type == 2) && (val > USCounter)) + {//printf("[CLIENT %01X] received sync2: %016llX\n", aid, val); + NextSync = val; + SyncBack = true; + break; + } + } + /*if (sync) + { + NextSync = USCounter - sync; + }*/ + } } if (IOPORT(W_CmdCountCnt) & 0x0001) @@ -1091,11 +1538,20 @@ void USTimer(u32 param) if ((RXBuffer[0] & 0x0F) == 0x0C) { + // src=16 dst=4 bss=10 + memcpy(MPHostMAC, &RXBuffer[0xC + 16], 6); + memcpy(MPHostBSS, &RXBuffer[0xC + 10], 6); + MPHostSeqNo = *(u16*)&RXBuffer[0xC + 22]; + u16 clientmask = *(u16*)&RXBuffer[0xC + 26]; if (IOPORT(W_AIDLow) && (RXBuffer[0xC + 4] & 0x01) && (clientmask & (1 << IOPORT(W_AIDLow)))) { SendMPReply(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]); } + /*else if (RXBuffer[0xC + 4] & 0x01) + { + DummyMPReplyFrame(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]); + }*/ } } @@ -1168,6 +1624,15 @@ u16 Read(u32 addr) //printf("WIFI: read %08X\n", addr); if (addr >= 0x4000 && addr < 0x6000) { + //if (addr>=0x4000 && addr<0x400C) printf("READ TX HEADER 0480%04X, %08X\n", addr, NDS::GetPC(1)); + //if (addr>=0x4234 && addr<0x4240) printf("READ TX HEADER 0480%04X, %08X\n", addr, NDS::GetPC(1)); + //if (RXBuffer[12] == 0x0228) + { + //u16 headeraddr = IOPORT(W_RXBufReadCursor) << 1; + //if ((addr & 0x1FFE) == (headeraddr + 12 + 28)) + //if (*(u16*)&RAM[(addr - 0x1C) & 0x1FFE] == 0x0228) + // printf("READ SHITTY CMD HEADER %08X\n", NDS::GetPC(1)); + } return *(u16*)&RAM[addr & 0x1FFE]; } if (addr >= 0x2000 && addr < 0x4000) @@ -1214,6 +1679,8 @@ u16 Read(u32 addr) { u32 rdaddr = IOPORT(W_RXBufReadAddr); + //if (*(u16*)&RAM[(rdaddr - 0x1C) & 0x1FFE] == 0x0228) + // printf("READ SHITTY CMD HEADER %08X\n", NDS::GetPC(1)); u16 ret = *(u16*)&RAM[rdaddr]; rdaddr += 2; @@ -1454,7 +1921,7 @@ void Write(u32 addr, u16 val) case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return; case W_USCompare3: USCompare = (USCompare & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); return; - case W_CmdCount: CmdCounter = val * 10; return; + case W_CmdCount: /*printf("CMDCOUNT=%d (%04X)\n", val*10, val);*/ CmdCounter = val * 10; return; case W_BBCnt: IOPORT(W_BBCnt) = val; @@ -1570,6 +2037,7 @@ void Write(u32 addr, u16 val) case W_TXSlotCmd: // checkme: is it possible to cancel a queued transfer that hasn't started yet // by clearing bit15 here? + // TODO: "W_TXBUF_CMD.Bit15 can be set ONLY while W_CMD_COUNT is non-zero." IOPORT(addr&0xFFF) = val; FireTX(); return; @@ -1597,7 +2065,11 @@ void Write(u32 addr, u16 val) case 0x214: case 0x268: return; - + + case W_RXFilter: + //printf("wifi: stupid RX filter=%04X\n", val); + break; + default: //printf("WIFI unk: write %08X %04X\n", addr, val); break; diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 4306c988..4c3c714b 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -55,6 +55,7 @@ #include "ROMManager.h" #include "LAN_Socket.h" #include "LAN_PCap.h" +#include "SPI.h" #include #ifndef INVALID_SOCKET @@ -65,16 +66,17 @@ std::string EmuDirectory; void emuStop(); - +extern u16 zanf; namespace Platform { -socket_t MPSocket; -sockaddr_t MPSendAddr; +u32 MPUniqueID; +socket_t MPSocket[2]; +sockaddr_t MPSendAddr[2]; u8 PacketBuffer[2048]; -#define NIFI_VER 1 +#define NIFI_VER 2 void Init(int argc, char** argv) @@ -386,10 +388,38 @@ void WriteGBASave(const u8* savedata, u32 savelen, u32 writeoffset, u32 writelen } +void _logpacket(bool tx, u8* data, int len) +{return; + char path[256]; + sprintf(path, "framelog_%08X.log", MPUniqueID); + static FILE* f = nullptr; + if (!f) f = fopen(path, "a"); + + /*fprintf(f, "---- %s PACKET LEN=%d ----\n", tx?"SENDING":"RECEIVING", len); + + for (int y = 0; y < len; y+=16) + { + fprintf(f, "%04X: ", y); + int linelen = 16; + if ((y+linelen) > len) linelen = len-y; + for (int x = 0; x < linelen; x++) + { + fprintf(f, " %02X", data[y+x]); + } + fprintf(f, "\n"); + } + + fprintf(f, "-------------------------------------\n\n\n");*/ + + fprintf(f, "%s PACKET: LEN=%0.4d FC=%04X SN=%04X CL=%04X/%04X\n", tx?"TX":"RX", + len, *(u16*)&data[12], *(u16*)&data[12+22], *(u16*)&data[12+24], *(u16*)&data[12+26]); + fflush(f); +} + bool MP_Init() { int opt_true = 1; - int res; + int res0, res1; #ifdef __WIN32__ WSADATA wsadata; @@ -399,26 +429,40 @@ bool MP_Init() } #endif // __WIN32__ - MPSocket = socket(AF_INET, SOCK_DGRAM, 0); - if (MPSocket < 0) + MPSocket[0] = socket(AF_INET, SOCK_DGRAM, 0); + if (MPSocket[0] < 0) { return false; } - res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); - if (res < 0) + MPSocket[1] = socket(AF_INET, SOCK_DGRAM, 0); + if (MPSocket[1] < 0) { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; + closesocket(MPSocket[0]); + MPSocket[0] = INVALID_SOCKET; + return false; + } + + res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); + res1 = setsockopt(MPSocket[1], SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int)); + if (res0 < 0 || res1 < 0) + { + closesocket(MPSocket[0]); + MPSocket[0] = INVALID_SOCKET; + closesocket(MPSocket[1]); + MPSocket[1] = INVALID_SOCKET; return false; } #if defined(BSD) || defined(__APPLE__) - res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int)); - if (res < 0) + res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int)); + res0 = setsockopt(MPSocket[1], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int)); + if (res0 < 0 || res1 < 0) { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; + closesocket(MPSocket[0]); + MPSocket[0] = INVALID_SOCKET; + closesocket(MPSocket[1]); + MPSocket[1] = INVALID_SOCKET; return false; } #endif @@ -427,33 +471,51 @@ bool MP_Init() saddr.sa_family = AF_INET; *(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK); *(u16*)&saddr.sa_data[0] = htons(7064); - res = bind(MPSocket, &saddr, sizeof(sockaddr_t)); - if (res < 0) + res0 = bind(MPSocket[0], &saddr, sizeof(sockaddr_t)); + *(u16*)&saddr.sa_data[0] = htons(7065); + res1 = bind(MPSocket[1], &saddr, sizeof(sockaddr_t)); + if (res0 < 0 || res1 < 0) { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; + closesocket(MPSocket[0]); + MPSocket[0] = INVALID_SOCKET; + closesocket(MPSocket[1]); + MPSocket[1] = INVALID_SOCKET; return false; } - res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); - if (res < 0) + res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); + res1 = setsockopt(MPSocket[1], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int)); + if (res0 < 0 || res1 < 0) { - closesocket(MPSocket); - MPSocket = INVALID_SOCKET; + closesocket(MPSocket[0]); + MPSocket[0] = INVALID_SOCKET; + closesocket(MPSocket[1]); + MPSocket[1] = INVALID_SOCKET; return false; } - MPSendAddr.sa_family = AF_INET; - *(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST); - *(u16*)&MPSendAddr.sa_data[0] = htons(7064); + MPSendAddr[0].sa_family = AF_INET; + *(u32*)&MPSendAddr[0].sa_data[2] = htonl(INADDR_BROADCAST); + *(u16*)&MPSendAddr[0].sa_data[0] = htons(7064); + + MPSendAddr[1].sa_family = AF_INET; + *(u32*)&MPSendAddr[1].sa_data[2] = htonl(INADDR_BROADCAST); + *(u16*)&MPSendAddr[1].sa_data[0] = htons(7065); + + u8* mac = SPI_Firmware::GetWifiMAC(); + MPUniqueID = *(u32*)&mac[0]; + MPUniqueID ^= *(u32*)&mac[2]; + printf("local MP unique ID: %08X\n", MPUniqueID); return true; } void MP_DeInit() { - if (MPSocket >= 0) - closesocket(MPSocket); + if (MPSocket[0] >= 0) + closesocket(MPSocket[0]); + if (MPSocket[1] >= 0) + closesocket(MPSocket[1]); #ifdef __WIN32__ WSACleanup(); @@ -462,10 +524,10 @@ void MP_DeInit() int MP_SendPacket(u8* data, int len) { - if (MPSocket < 0) + if (MPSocket[0] < 0) return 0; - if (len > 2048-8) + if (len > 2048-12) { printf("MP_SendPacket: error: packet too long (%d)\n", len); return 0; @@ -475,57 +537,216 @@ int MP_SendPacket(u8* data, int len) PacketBuffer[4] = NIFI_VER; PacketBuffer[5] = 0; *(u16*)&PacketBuffer[6] = htons(len); - memcpy(&PacketBuffer[8], data, len); + *(u32*)&PacketBuffer[8] = MPUniqueID; + memcpy(&PacketBuffer[12], data, len); - int slen = sendto(MPSocket, (const char*)PacketBuffer, len+8, 0, &MPSendAddr, sizeof(sockaddr_t)); - if (slen < 8) return 0; - return slen - 8; + _logpacket(true, data, len); + + int slen = sendto(MPSocket[0], (const char*)PacketBuffer, len+12, 0, &MPSendAddr[0], sizeof(sockaddr_t)); + if (slen < 12) return 0; + return slen - 12; } int MP_RecvPacket(u8* data, bool block) { - if (MPSocket < 0) + if (MPSocket[0] < 0) return 0; fd_set fd; struct timeval tv; - FD_ZERO(&fd); - FD_SET(MPSocket, &fd); - tv.tv_sec = 0; - tv.tv_usec = block ? 5000 : 0; - - if (!select(MPSocket+1, &fd, 0, 0, &tv)) + for (;;) { + FD_ZERO(&fd); + FD_SET(MPSocket[0], &fd); + tv.tv_sec = 0; + //tv.tv_usec = block ? 5000 : 0; + tv.tv_usec = block ? 500*1000 : 0; + + if (!select(MPSocket[0]+1, &fd, 0, 0, &tv)) + { + return 0; + } + + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + int rlen = recvfrom(MPSocket[0], (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen); + if (rlen < 12+24) + { + continue; + } + rlen -= 12; + + if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E) + { + continue; + } + + if (PacketBuffer[4] != NIFI_VER || PacketBuffer[5] != 0) + { + continue; + } + + if (ntohs(*(u16*)&PacketBuffer[6]) != rlen) + { + continue; + } + + if (*(u32*)&PacketBuffer[8] == MPUniqueID) + { + continue; + } + + zanf = *(u16*)&PacketBuffer[12+6]; + _logpacket(false, &PacketBuffer[12], rlen); + + memcpy(data, &PacketBuffer[12], rlen); + return rlen; + } +} + +bool MP_SendSync(u16 clientmask, u16 type, u64 val) +{ + u8 syncbuf[32]; + + if (MPSocket[1] < 0) + return false; + + int len = 16; + *(u32*)&syncbuf[0] = htonl(0x4946494E); // NIFI + syncbuf[4] = NIFI_VER; + syncbuf[5] = 1; + *(u16*)&syncbuf[6] = htons(len); + *(u16*)&syncbuf[8] = htons(type); + *(u16*)&syncbuf[10] = htons(clientmask); + *(u32*)&syncbuf[12] = MPUniqueID; + *(u32*)&syncbuf[16] = htonl((u32)val); + *(u32*)&syncbuf[20] = htonl((u32)(val>>32)); + + int slen = sendto(MPSocket[1], (const char*)syncbuf, len+8, 0, &MPSendAddr[1], sizeof(sockaddr_t)); + return slen == len+8; +} + +bool MP_WaitSync(u16 clientmask, u16* type, u64* val) +{ + u8 syncbuf[32]; + + if (MPSocket[1] < 0) + return false; + + fd_set fd; + struct timeval tv; + + for (;;) + { + FD_ZERO(&fd); + FD_SET(MPSocket[1], &fd); + tv.tv_sec = 0; + tv.tv_usec = 500*1000; + + if (!select(MPSocket[1]+1, &fd, 0, 0, &tv)) + {printf("sync fail\n"); + return false; + } + + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + int rlen = recvfrom(MPSocket[1], (char*)syncbuf, 32, 0, &fromAddr, &fromLen); + if (rlen != 8+16) + continue; + rlen -= 8; + + if (ntohl(*(u32*)&syncbuf[0]) != 0x4946494E) + continue; + + if (syncbuf[4] != NIFI_VER || syncbuf[5] != 1) + continue; + + if (ntohs(*(u16*)&syncbuf[6]) != rlen) + continue; + + if (*(u32*)&syncbuf[12] == MPUniqueID) + continue; + + u16 clientval = ntohs(*(u16*)&syncbuf[10]); + if (!(clientmask & clientval)) + continue; + + // check the sync val, it should be ahead of the current sync val + u64 syncval = ntohl(*(u32*)&syncbuf[16]) | (((u64)ntohl(*(u32*)&syncbuf[20])) << 32); + //if (syncval <= curval) + // continue; + + if (type) *type = ntohs(*(u16*)&syncbuf[8]); + if (val) *val = syncval; + + return true; + } +} + +u16 MP_WaitMultipleSyncs(u16 type, u16 clientmask, u64 curval) +{ + u8 syncbuf[32]; + + if (!clientmask) return 0; + + if (MPSocket[1] < 0) + return 0; + + fd_set fd; + struct timeval tv; + + for (;;) + { + FD_ZERO(&fd); + FD_SET(MPSocket[1], &fd); + tv.tv_sec = 0; + tv.tv_usec = 500*1000; + + if (!select(MPSocket[1]+1, &fd, 0, 0, &tv)) + {printf("[sync3] nope :(\n"); + return clientmask; + } + + sockaddr_t fromAddr; + socklen_t fromLen = sizeof(sockaddr_t); + int rlen = recvfrom(MPSocket[1], (char*)syncbuf, 32, 0, &fromAddr, &fromLen); + if (rlen != 8+16) + continue; + rlen -= 8; + + if (ntohl(*(u32*)&syncbuf[0]) != 0x4946494E) + continue; + + if (syncbuf[4] != NIFI_VER || syncbuf[5] != 1) + continue; +//printf("[sync3] atleast header is good\n"); + if (ntohs(*(u16*)&syncbuf[6]) != rlen) + continue; + + if (*(u32*)&syncbuf[12] == MPUniqueID) + continue; + + if (ntohs(*(u16*)&syncbuf[8]) != type) + continue; + + u16 clientval = ntohs(*(u16*)&syncbuf[10]); + //printf("[sync3] good rlen/type %04X %04X, clientmask=%04X \n", ntohs(*(u16*)&syncbuf[6]), ntohs(*(u16*)&syncbuf[8]), clientval); + if (!(clientmask & clientval)) + continue; + + // check the sync val, it should be ahead of the current sync val + u64 syncval = ntohl(*(u32*)&syncbuf[12]) | (((u64)ntohl(*(u32*)&syncbuf[16])) << 32); + //if (syncval <= curval) + // continue; +//printf("[sync3] good\n"); + clientmask &= ~clientval; + //if (!clientmask) + return 0; } - sockaddr_t fromAddr; - socklen_t fromLen = sizeof(sockaddr_t); - int rlen = recvfrom(MPSocket, (char*)PacketBuffer, 2048, 0, &fromAddr, &fromLen); - if (rlen < 8+24) - { - return 0; - } - rlen -= 8; - - if (ntohl(*(u32*)&PacketBuffer[0]) != 0x4946494E) - { - return 0; - } - - if (PacketBuffer[4] != NIFI_VER) - { - return 0; - } - - if (ntohs(*(u16*)&PacketBuffer[6]) != rlen) - { - return 0; - } - - memcpy(data, &PacketBuffer[8], rlen); - return rlen; + return clientmask; } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 2401a53a..3c1b588a 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -1475,6 +1476,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent) actTitleManager = menu->addAction("Manage DSi titles"); connect(actTitleManager, &QAction::triggered, this, &MainWindow::onOpenTitleManager); + + // TEST!! + menu->addSeparator(); + actTest = menu->addAction("Fart"); + connect(actTest, &QAction::triggered, this, &MainWindow::onTest); } { QMenu* menu = menubar->addMenu("Config"); @@ -1828,7 +1834,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event) if (event->isAutoRepeat()) return; // TODO!! REMOVE ME IN RELEASE BUILDS!! - //if (event->key() == Qt::Key_F11) NDS::debug(0); + if (event->key() == Qt::Key_F11) NDS::debug(0); Input::KeyPress(event); } @@ -2602,6 +2608,17 @@ void MainWindow::onOpenTitleManager() TitleManagerDialog* dlg = TitleManagerDialog::openDlg(this); } +void MainWindow::onTest() +{ + //QProcess::startDetached(QApplication::applicationFilePath()); + QProcess ass; + ass.setCreateProcessArgumentsModifier([] (QProcess::CreateProcessArguments *args) + { + args->flags |= CREATE_NEW_CONSOLE; + }); + ass.startDetached(QApplication::applicationFilePath()); +} + void MainWindow::onOpenEmuSettings() { emuThread->emuPause(); @@ -3180,12 +3197,13 @@ 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)) + if (AllocConsole()) { freopen("CONOUT$", "w", stdout); freopen("CONOUT$", "w", stderr); printf("\n"); - }*/ + } int ret = main(argc, argv); diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 45d1da01..0af0798b 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -255,6 +255,7 @@ private slots: void onROMInfo(); void onRAMInfo(); void onOpenTitleManager(); + void onTest(); void onOpenEmuSettings(); void onEmuSettingsDialogFinished(int res); @@ -344,6 +345,7 @@ public: QAction* actROMInfo; QAction* actRAMInfo; QAction* actTitleManager; + QAction* actTest; QAction* actEmuSettings; QAction* actPowerManagement;