start implementing MP-comm error handling

This commit is contained in:
Arisotura 2022-08-21 13:37:31 +02:00
parent 5db8499787
commit 639ed7b150
3 changed files with 73 additions and 73 deletions

View File

@ -1942,7 +1942,7 @@ void debug(u32 param)
// printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]); // printf("VRAM %c: %02X\n", 'A'+i, GPU::VRAMCNT[i]);
FILE* FILE*
shit = fopen("debug/pictochat.bin", "wb"); shit = fopen("debug/tetrisDS.bin", "wb");
fwrite(ARM9->ITCM, 0x8000, 1, shit); fwrite(ARM9->ITCM, 0x8000, 1, shit);
for (u32 i = 0x02000000; i < 0x02400000; i+=4) for (u32 i = 0x02000000; i < 0x02400000; i+=4)
{ {

View File

@ -26,6 +26,7 @@
#include "ARM.h" #include "ARM.h"
#include "GPU.h" #include "GPU.h"
u16 zanf = 2423; u16 zanf = 2423;
namespace LocalMP { void _logstring(u64 ts, char* str);void _logstring2(u64 ts, char* str, u32 arg, u64 arg2); }
namespace Wifi namespace Wifi
{ {
@ -86,11 +87,8 @@ u32 TXCurSlot;
u32 RXCounter; u32 RXCounter;
int MPReplyTimer; int MPReplyTimer;
int MPNumReplies; u16 MPCurClient;
int MPReplyFrame; // for client u16 MPClientMask, MPClientFail;
u8 MPHostMAC[6];
u8 MPHostBSS[6];
u16 MPHostSeqNo;
bool MPInited; bool MPInited;
bool LANInited; bool LANInited;
@ -232,11 +230,8 @@ void Reset()
RXTimestamp = 0; RXTimestamp = 0;
MPReplyTimer = 0; MPReplyTimer = 0;
MPNumReplies = 0; MPClientMask = 0;
MPReplyFrame = 0; MPClientFail = 0;
memset(MPHostMAC, 0, 6);
memset(MPHostBSS, 0, 6);
MPHostSeqNo = 0;
CmdCounter = 0; CmdCounter = 0;
@ -277,7 +272,7 @@ void DoSavestate(Savestate* file)
file->Var32(&RXCounter); file->Var32(&RXCounter);
file->Var32((u32*)&MPReplyTimer); file->Var32((u32*)&MPReplyTimer);
file->Var32((u32*)&MPNumReplies); //file->Var32((u32*)&MPNumReplies);
file->Var32(&CmdCounter); file->Var32(&CmdCounter);
} }
@ -547,19 +542,6 @@ void SendMPReply(u16 clienttime, u16 clientmask)
slot->CurPhaseTime = 16 + ((clienttime + 10) * clientnum) + PreambleLen(slot->Rate); 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; IOPORT(W_TXBusy) |= 0x0080;
} }
@ -595,7 +577,7 @@ void SendMPDefaultReply()
WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen); WIFI_LOG("wifi: sent %d/40 bytes of MP default reply\n", txlen);
} }
void SendMPAck() void SendMPAck(u16 clientfail)
{ {
u8 ack[12 + 32]; u8 ack[12 + 32];
@ -618,7 +600,7 @@ void SendMPAck()
*(u16*)&ack[0xC + 0x14] = IOPORT(W_MACAddr2); *(u16*)&ack[0xC + 0x14] = IOPORT(W_MACAddr2);
*(u16*)&ack[0xC + 0x16] = IOPORT(W_TXSeqNo) << 4; *(u16*)&ack[0xC + 0x16] = IOPORT(W_TXSeqNo) << 4;
*(u16*)&ack[0xC + 0x18] = 0x0033; // ??? *(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; *(u32*)&ack[0xC + 0x1C] = 0;
int txlen = Platform::MP_SendPacket(ack, 12+32, USTimestamp); int txlen = Platform::MP_SendPacket(ack, 12+32, USTimestamp);
@ -640,36 +622,22 @@ bool ProcessTX(TXSlot* slot, int num)
else if (slot->CurPhase == 2) else if (slot->CurPhase == 2)
{ {
MPReplyTimer--; MPReplyTimer--;
if (MPReplyTimer == 0 && MPNumReplies > 0) if (MPReplyTimer == 0 && MPClientMask != 0)
{ {
u32 curclient = 0x0002;
while (!(MPClientMask & curclient)) curclient <<= 1;
if (CheckRX(true)) if (CheckRX(true))
{ {
if (slot->Length==34) // we received a reply, mark it as such
{ // TODO: is any received packet considered a good reply?
u32 len = *(u16*)&RXBuffer[8]; // hardware probably requires a specific frame-control and/or destination MAC
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 MPClientFail &= ~curclient;
// also, if the reply is too big to fit within its window, what happens? }
MPReplyTimer = 10 + IOPORT(W_CmdReplyTime); MPReplyTimer = 10 + IOPORT(W_CmdReplyTime);
MPNumReplies--; MPClientMask &= ~curclient;
} }
} }
@ -849,8 +817,8 @@ bool ProcessTX(TXSlot* slot, int num)
case 1: // transmit done case 1: // transmit done
{ {
// for the MP reply slot, this is set later // for the MP CMD and reply slots, this is set later
if (num != 5) if (num != 1 && num != 5)
*(u16*)&RAM[slot->Addr] = 0x0001; *(u16*)&RAM[slot->Addr] = 0x0001;
RAM[slot->Addr + 5] = 0; RAM[slot->Addr + 5] = 0;
@ -864,13 +832,15 @@ bool ProcessTX(TXSlot* slot, int num)
SetStatus(5); SetStatus(5);
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2];
MPNumReplies = NumClients(clientmask); //MPNumReplies = NumClients(clientmask);
MPReplyTimer = 16 + PreambleLen(slot->Rate); MPReplyTimer = 16 + PreambleLen(slot->Rate);
MPClientMask = clientmask;
MPClientFail = clientmask;
// TODO: 112 likely includes the ack preamble, which needs adjusted // TODO: 112 likely includes the ack preamble, which needs adjusted
// for long-preamble settings // for long-preamble settings
slot->CurPhase = 2; slot->CurPhase = 2;
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * MPNumReplies); slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * NumClients(clientmask));
break; break;
} }
@ -938,9 +908,10 @@ bool ProcessTX(TXSlot* slot, int num)
//printf("[HOST] sending CMD, sent sync2, waiting\n"); //printf("[HOST] sending CMD, sent sync2, waiting\n");
//u16 res = Platform::MP_WaitMultipleSyncs(3, /*clientmask*/0x0002, USCounter); //u16 res = Platform::MP_WaitMultipleSyncs(3, /*clientmask*/0x0002, USCounter);
//printf("[HOST] got sync3: %04X\n", res); //printf("[HOST] got sync3: %04X\n", res);
if (MPClientFail) printf("client fail: %04X (%04X)\n", MPClientFail, clientmask);
// send // send
SendMPAck(); SendMPAck(MPClientFail);
// send further sync // send further sync
//Platform::MP_SendSync(/*clientmask*/0x0002, 1, USCounter + slot->CurPhaseTime); //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_TXBusy) &= ~(1<<1);
IOPORT(W_TXSlotCmd) &= 0x7FFF; // confirmed IOPORT(W_TXSlotCmd) &= 0x7FFF; // confirmed
// seems this is set to indicate which clients failed to reply if (!MPClientFail)
*(u16*)&RAM[slot->Addr + 0x2] = 0; *(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); 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) if (IOPORT(W_TXStatCnt) & 0x2000)
{ {
@ -974,6 +945,11 @@ bool ProcessTX(TXSlot* slot, int num)
} }
SetStatus(1); 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 // let clients run ahead some
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2]; u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2];
//Platform::MP_SendSync(clientmask, 1, kMaxRunahead); //Platform::MP_SendSync(clientmask, 1, kMaxRunahead);
@ -1037,6 +1013,7 @@ void StartRX()
//printf("%016llX: starting receiving packet %04X\n", USTimestamp, *(u16*)&RXBuffer[12]); //printf("%016llX: starting receiving packet %04X\n", USTimestamp, *(u16*)&RXBuffer[12]);
//if (zamf != USTimestamp) //if (zamf != USTimestamp)
// printf("PACKET %04X DESYNCED: %016llX =/= %016llX\n", *(u16*)&RXBuffer[12], 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; u16 zarp = 0;
@ -1149,6 +1126,7 @@ bool CheckRX(bool local)
break; break;
} }
//printf("received %04X time=%04X client=%04X\n", framectl, *(u16*)&RXBuffer[12+24], *(u16*)&RXBuffer[12+26]); //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", 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)); 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", //if (framectl==0x0228) printf("RX CMD: len=%d, client=%04X, rxfilter=%04X/%04X\n",
@ -1227,7 +1205,7 @@ zamf = timestamp;
RXTimestamp = timestamp; RXTimestamp = timestamp;
NextSync = timestamp + (framelen * (txrate==0x14 ? 4:8)); NextSync = timestamp + (framelen * (txrate==0x14 ? 4:8));
if (RXTimestamp < USTimestamp) printf("!!! RECEIVED FRAME IN THE PAST\n");
if ((rxflags & 0xF) == 0xC) if ((rxflags & 0xF) == 0xC)
{ {
u16 clienttime = *(u16*)&RXBuffer[12+24]; u16 clienttime = *(u16*)&RXBuffer[12+24];
@ -1469,20 +1447,17 @@ void USTimer(u32 param)
SetStatus(1); 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]); //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]); 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; ComStatus &= ~0x1;
RXCounter = 0; RXCounter = 0;
if ((RXBuffer[0] & 0x0F) == 0x0C) 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]; u16 clientmask = *(u16*)&RXBuffer[0xC + 26];
if (IOPORT(W_AIDLow) && (RXBuffer[0xC + 4] & 0x01) && (clientmask & (1 << IOPORT(W_AIDLow)))) if (IOPORT(W_AIDLow) && (RXBuffer[0xC + 4] & 0x01) && (clientmask & (1 << IOPORT(W_AIDLow))))
{//printf("%016llX: sending MP reply\n", USTimestamp); {//printf("%016llX: sending MP reply\n", USTimestamp);
LocalMP::_logstring(USTimestamp, "SENDING MP REPLY");
SendMPReply(*(u16*)&RXBuffer[0xC + 24], clientmask); SendMPReply(*(u16*)&RXBuffer[0xC + 24], clientmask);
} }
} }
@ -1743,6 +1718,7 @@ void Write(u32 addr, u16 val)
return; return;
case W_AIDLow: case W_AIDLow:
//printf("[%016llX] AIDLOW=%04X (%08X)\n", USTimestamp, val, NDS::GetPC(1));
IOPORT(W_AIDLow) = val & 0x000F; IOPORT(W_AIDLow) = val & 0x000F;
return; return;
case W_AIDFull: case W_AIDFull:

View File

@ -165,10 +165,10 @@ bool SemWait(int num, int timeout)
#endif // _WIN32 #endif // _WIN32
void _logpacket(bool tx, u8* data, int len) void _logpacket(bool tx, u8* data, int len, u64 ts)
{return; {return;
char path[256]; char path[256];
sprintf(path, "framelog_%08X.log", MPUniqueID); sprintf(path, "framelog_%08X.log", InstanceID);
static FILE* f = nullptr; static FILE* f = nullptr;
if (!f) f = fopen(path, "a"); 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, "-------------------------------------\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]); len, *(u16*)&data[12], *(u16*)&data[12+22], *(u16*)&data[12+24], *(u16*)&data[12+26]);
fflush(f); 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() bool Init()
{ {
/*int opt_true = 1; /*int opt_true = 1;
@ -407,6 +429,7 @@ void PacketFIFOWrite(void* buf, int len)
int SendPacket(u8* packet, int len, u64 timestamp) int SendPacket(u8* packet, int len, u64 timestamp)
{ {
_logpacket(true, packet, len, timestamp);
MPQueue->lock(); MPQueue->lock();
u8* data = (u8*)MPQueue->data(); u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0]; MPQueueHeader* header = (MPQueueHeader*)&data[0];
@ -469,6 +492,7 @@ int RecvPacket(u8* packet, bool block, u64* timestamp)
} }
PacketFIFORead(packet, pktheader.Length); PacketFIFORead(packet, pktheader.Length);
_logpacket(false, packet, pktheader.Length, pktheader.Timestamp);
if (timestamp) *timestamp = pktheader.Timestamp; if (timestamp) *timestamp = pktheader.Timestamp;
MPQueue->unlock(); MPQueue->unlock();
return pktheader.Length; return pktheader.Length;