From 639ed7b150c66b91b36eeaa2c704117062fa879a Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sun, 21 Aug 2022 13:37:31 +0200 Subject: [PATCH] start implementing MP-comm error handling --- src/NDS.cpp | 2 +- src/Wifi.cpp | 114 +++++++++++++------------------- src/frontend/qt_sdl/LocalMP.cpp | 30 ++++++++- 3 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/NDS.cpp b/src/NDS.cpp index f72a2ab1..6d62376b 100644 --- a/src/NDS.cpp +++ b/src/NDS.cpp @@ -1942,7 +1942,7 @@ void debug(u32 param) // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); FILE* - shit = fopen("debug/pictochat.bin", "wb"); + shit = fopen("debug/tetrisDS.bin", "wb"); fwrite(ARM9->ITCM, 0x8000, 1, shit); for (u32 i = 0x02000000; i < 0x02400000; i+=4) { diff --git a/src/Wifi.cpp b/src/Wifi.cpp index 1cb47c5d..f3ae94f7 100644 --- a/src/Wifi.cpp +++ b/src/Wifi.cpp @@ -26,6 +26,7 @@ #include "ARM.h" #include "GPU.h" u16 zanf = 2423; +namespace LocalMP { void _logstring(u64 ts, char* str);void _logstring2(u64 ts, char* str, u32 arg, u64 arg2); } namespace Wifi { @@ -86,11 +87,8 @@ u32 TXCurSlot; u32 RXCounter; int MPReplyTimer; -int MPNumReplies; -int MPReplyFrame; // for client -u8 MPHostMAC[6]; -u8 MPHostBSS[6]; -u16 MPHostSeqNo; +u16 MPCurClient; +u16 MPClientMask, MPClientFail; bool MPInited; bool LANInited; @@ -232,11 +230,8 @@ void Reset() RXTimestamp = 0; MPReplyTimer = 0; - MPNumReplies = 0; - MPReplyFrame = 0; - memset(MPHostMAC, 0, 6); - memset(MPHostBSS, 0, 6); - MPHostSeqNo = 0; + MPClientMask = 0; + MPClientFail = 0; CmdCounter = 0; @@ -277,7 +272,7 @@ void DoSavestate(Savestate* file) file->Var32(&RXCounter); file->Var32((u32*)&MPReplyTimer); - file->Var32((u32*)&MPNumReplies); + //file->Var32((u32*)&MPNumReplies); file->Var32(&CmdCounter); } @@ -547,19 +542,6 @@ void SendMPReply(u16 clienttime, u16 clientmask) 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; } @@ -595,7 +577,7 @@ void SendMPDefaultReply() WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen); } -void SendMPAck() +void SendMPAck(u16 clientfail) { u8 ack[12 + 32]; @@ -618,7 +600,7 @@ 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; // TODO: bitmask of which clients failed to reply + *(u16*)&ack[0xC + 0x1A] = clientfail; *(u32*)&ack[0xC + 0x1C] = 0; int txlen = Platform::MP_SendPacket(ack, 12+32, USTimestamp); @@ -640,36 +622,22 @@ bool ProcessTX(TXSlot* slot, int num) else if (slot->CurPhase == 2) { MPReplyTimer--; - if (MPReplyTimer == 0 && MPNumReplies > 0) + if (MPReplyTimer == 0 && MPClientMask != 0) { + u32 curclient = 0x0002; + while (!(MPClientMask & curclient)) curclient <<= 1; + if (CheckRX(true)) { - if (slot->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"); + // we received a reply, mark it as such + // TODO: is any received packet considered a good reply? + // hardware probably requires a specific frame-control and/or destination MAC - // TODO: properly handle reply errors - // also, if the reply is too big to fit within its window, what happens? + MPClientFail &= ~curclient; + } MPReplyTimer = 10 + IOPORT(W_CmdReplyTime); - MPNumReplies--; + MPClientMask &= ~curclient; } } @@ -849,8 +817,8 @@ bool ProcessTX(TXSlot* slot, int num) case 1: // transmit done { - // for the MP reply slot, this is set later - if (num != 5) + // for the MP CMD and reply slots, this is set later + if (num != 1 && num != 5) *(u16*)&RAM[slot->Addr] = 0x0001; RAM[slot->Addr + 5] = 0; @@ -864,13 +832,15 @@ bool ProcessTX(TXSlot* slot, int num) SetStatus(5); u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; - MPNumReplies = NumClients(clientmask); + //MPNumReplies = NumClients(clientmask); MPReplyTimer = 16 + PreambleLen(slot->Rate); + MPClientMask = clientmask; + MPClientFail = clientmask; // 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); + slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(clientmask)); break; } @@ -938,9 +908,10 @@ bool ProcessTX(TXSlot* slot, int num) //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 (MPClientFail) printf("client fail: %04X (%04X)\n", MPClientFail, clientmask); // send - SendMPAck(); + SendMPAck(MPClientFail); // send further sync //Platform::MP_SendSync(/*clientmask*/0x0002, 1, USCounter + slot->CurPhaseTime); @@ -956,16 +927,16 @@ bool ProcessTX(TXSlot* slot, int num) IOPORT(W_TXBusy) &= ~(1<<1); IOPORT(W_TXSlotCmd) &= 0x7FFF; // confirmed - // seems this is set to indicate which clients failed to reply - *(u16*)&RAM[slot->Addr + 0x2] = 0; + if (!MPClientFail) + *(u16*)&RAM[slot->Addr] = 0x0001; + else + *(u16*)&RAM[slot->Addr] = 0x0005; + + // this is set to indicate which clients failed to reply + *(u16*)&RAM[slot->Addr + 0x2] = MPClientFail; IncrementTXCount(slot); - SetIRQ(12); - - //if (!(IOPORT(W_TXSlotCmd) & 0x4000)) - { - IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; - } + IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF; if (IOPORT(W_TXStatCnt) & 0x2000) { @@ -974,6 +945,11 @@ bool ProcessTX(TXSlot* slot, int num) } SetStatus(1); + // TODO: retry the whole cycle if some clients failed to respond + // AND if there is enough time left in CMDCOUNT + // (games seem to always configure CMDCOUNT such that there is no time for retries) + SetIRQ(12); + // let clients run ahead some u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; //Platform::MP_SendSync(clientmask, 1, kMaxRunahead); @@ -1037,6 +1013,7 @@ void StartRX() //printf("%016llX: starting receiving packet %04X\n", USTimestamp, *(u16*)&RXBuffer[12]); //if (zamf != USTimestamp) // printf("PACKET %04X DESYNCED: %016llX =/= %016llX\n", *(u16*)&RXBuffer[12], zamf, USTimestamp); + LocalMP::_logstring2(USTimestamp, "STARTING RX", ((*(u16*)&RXBuffer[12])<<16)|(*(u16*)&RXBuffer[12+26]), RXTimestamp); } u16 zarp = 0; @@ -1149,6 +1126,7 @@ bool CheckRX(bool local) break; } //printf("received %04X time=%04X client=%04X\n", framectl, *(u16*)&RXBuffer[12+24], *(u16*)&RXBuffer[12+26]); + LocalMP::_logstring2(USTimestamp, "RECEIVING FRAME", (framectl<<16)|(*(u16*)&RXBuffer[12+26]), timestamp); 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", @@ -1227,7 +1205,7 @@ zamf = timestamp; RXTimestamp = timestamp; NextSync = timestamp + (framelen * (txrate==0x14 ? 4:8)); - +if (RXTimestamp < USTimestamp) printf("!!! RECEIVED FRAME IN THE PAST\n"); if ((rxflags & 0xF) == 0xC) { u16 clienttime = *(u16*)&RXBuffer[12+24]; @@ -1469,20 +1447,17 @@ void USTimer(u32 param) SetStatus(1); //printf("%016llX: finished receiving a frame, aid=%04X, FC=%04X, client=%04X\n", USTimestamp, IOPORT(W_AIDLow), *(u16*)&RXBuffer[0xC], *(u16*)&RXBuffer[0xC + 26]); WIFI_LOG("wifi: finished receiving packet %04X\n", *(u16*)&RXBuffer[12]); + LocalMP::_logstring2(USTimestamp, "FINISH RX", ((*(u16*)&RXBuffer[12])<<16)|(*(u16*)&RXBuffer[12+26]), RXTimestamp); ComStatus &= ~0x1; RXCounter = 0; 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)))) {//printf("%016llX: sending MP reply\n", USTimestamp); + LocalMP::_logstring(USTimestamp, "SENDING MP REPLY"); SendMPReply(*(u16*)&RXBuffer[0xC + 24], clientmask); } } @@ -1743,6 +1718,7 @@ void Write(u32 addr, u16 val) return; case W_AIDLow: + //printf("[%016llX] AIDLOW=%04X (%08X)\n", USTimestamp, val, NDS::GetPC(1)); IOPORT(W_AIDLow) = val & 0x000F; return; case W_AIDFull: diff --git a/src/frontend/qt_sdl/LocalMP.cpp b/src/frontend/qt_sdl/LocalMP.cpp index e5288255..06da6e0c 100644 --- a/src/frontend/qt_sdl/LocalMP.cpp +++ b/src/frontend/qt_sdl/LocalMP.cpp @@ -165,10 +165,10 @@ bool SemWait(int num, int timeout) #endif // _WIN32 -void _logpacket(bool tx, u8* data, int len) +void _logpacket(bool tx, u8* data, int len, u64 ts) {return; char path[256]; - sprintf(path, "framelog_%08X.log", MPUniqueID); + sprintf(path, "framelog_%08X.log", InstanceID); static FILE* f = nullptr; if (!f) f = fopen(path, "a"); @@ -188,11 +188,33 @@ void _logpacket(bool tx, u8* data, int len) fprintf(f, "-------------------------------------\n\n\n");*/ - fprintf(f, "%s PACKET: LEN=%0.4d FC=%04X SN=%04X CL=%04X/%04X\n", tx?"TX":"RX", + fprintf(f, "[%016llX] %s PACKET: LEN=%0.4d FC=%04X SN=%04X CL=%04X/%04X\n", ts, tx?"TX":"RX", len, *(u16*)&data[12], *(u16*)&data[12+22], *(u16*)&data[12+24], *(u16*)&data[12+26]); fflush(f); } +void _logstring(u64 ts, char* str) +{return; + char path[256]; + sprintf(path, "framelog_%08X.log", InstanceID); + static FILE* f = nullptr; + if (!f) f = fopen(path, "a"); + + fprintf(f, "[%016llX] %s\n", ts, str); + fflush(f); +} + +void _logstring2(u64 ts, char* str, u32 arg, u64 arg2) +{return; + char path[256]; + sprintf(path, "framelog_%08X.log", InstanceID); + static FILE* f = nullptr; + if (!f) f = fopen(path, "a"); + + fprintf(f, "[%016llX] %s %08X %016llX\n", ts, str, arg, arg2); + fflush(f); +} + bool Init() { /*int opt_true = 1; @@ -407,6 +429,7 @@ void PacketFIFOWrite(void* buf, int len) int SendPacket(u8* packet, int len, u64 timestamp) { + _logpacket(true, packet, len, timestamp); MPQueue->lock(); u8* data = (u8*)MPQueue->data(); MPQueueHeader* header = (MPQueueHeader*)&data[0]; @@ -469,6 +492,7 @@ int RecvPacket(u8* packet, bool block, u64* timestamp) } PacketFIFORead(packet, pktheader.Length); + _logpacket(false, packet, pktheader.Length, pktheader.Timestamp); if (timestamp) *timestamp = pktheader.Timestamp; MPQueue->unlock(); return pktheader.Length;