attempt at betterer wifi
* add preliminary sync mechanism * fix gaps in wifi implementation
This commit is contained in:
parent
b5073e6014
commit
ab15d7402a
16
src/ARM.cpp
16
src/ARM.cpp
|
@ -42,8 +42,6 @@
|
||||||
//
|
//
|
||||||
// MUL/MLA seems to take 1I on ARM9
|
// MUL/MLA seems to take 1I on ARM9
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
u32 ARM::ConditionTable[16] =
|
u32 ARM::ConditionTable[16] =
|
||||||
{
|
{
|
||||||
0xF0F0, // EQ
|
0xF0F0, // EQ
|
||||||
|
@ -770,6 +768,20 @@ void ARMv4::Execute()
|
||||||
AddCycles_C();
|
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!!!
|
// TODO optimize this shit!!!
|
||||||
if (Halted)
|
if (Halted)
|
||||||
{
|
{
|
||||||
|
|
19
src/NDS.cpp
19
src/NDS.cpp
|
@ -1941,8 +1941,8 @@ void debug(u32 param)
|
||||||
//for (int i = 0; i < 9; i++)
|
//for (int i = 0; i < 9; i++)
|
||||||
// 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/construct.bin", "wb");
|
shit = fopen("debug/pictochat.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)
|
||||||
{
|
{
|
||||||
|
@ -1954,9 +1954,9 @@ void debug(u32 param)
|
||||||
u32 val = ARM7Read32(i);
|
u32 val = ARM7Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);*/
|
fclose(shit);
|
||||||
|
|
||||||
FILE*
|
/*FILE*
|
||||||
shit = fopen("debug/directboot9.bin", "wb");
|
shit = fopen("debug/directboot9.bin", "wb");
|
||||||
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
for (u32 i = 0x02000000; i < 0x04000000; i+=4)
|
||||||
{
|
{
|
||||||
|
@ -1970,7 +1970,7 @@ void debug(u32 param)
|
||||||
u32 val = DSi::ARM7Read32(i);
|
u32 val = DSi::ARM7Read32(i);
|
||||||
fwrite(&val, 4, 1, shit);
|
fwrite(&val, 4, 1, shit);
|
||||||
}
|
}
|
||||||
fclose(shit);
|
fclose(shit);*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2425,6 +2425,15 @@ u8 ARM7Read8(u32 addr)
|
||||||
|
|
||||||
u16 ARM7Read16(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 (addr < 0x00004000)
|
||||||
{
|
{
|
||||||
if (ARM7->R[15] >= 0x00004000)
|
if (ARM7->R[15] >= 0x00004000)
|
||||||
|
|
|
@ -158,6 +158,9 @@ bool MP_Init();
|
||||||
void MP_DeInit();
|
void MP_DeInit();
|
||||||
int MP_SendPacket(u8* data, int len);
|
int MP_SendPacket(u8* data, int len);
|
||||||
int MP_RecvPacket(u8* data, bool block);
|
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
|
// LAN comm interface
|
||||||
// packet type: Ethernet (802.3)
|
// packet type: Ethernet (802.3)
|
||||||
|
|
570
src/Wifi.cpp
570
src/Wifi.cpp
|
@ -25,13 +25,15 @@
|
||||||
#include "Platform.h"
|
#include "Platform.h"
|
||||||
#include "ARM.h"
|
#include "ARM.h"
|
||||||
#include "GPU.h"
|
#include "GPU.h"
|
||||||
|
u16 zanf = 2423;
|
||||||
namespace Wifi
|
namespace Wifi
|
||||||
{
|
{
|
||||||
|
|
||||||
//#define WIFI_LOG printf
|
//#define WIFI_LOG printf
|
||||||
#define WIFI_LOG(...) {}
|
#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];
|
u8 RAM[0x2000];
|
||||||
u16 IO[0x1000>>1];
|
u16 IO[0x1000>>1];
|
||||||
|
|
||||||
|
@ -58,6 +60,7 @@ u32 RFRegs[0x40];
|
||||||
|
|
||||||
struct TXSlot
|
struct TXSlot
|
||||||
{
|
{
|
||||||
|
bool Valid;
|
||||||
u16 Addr;
|
u16 Addr;
|
||||||
u16 Length;
|
u16 Length;
|
||||||
u8 Rate;
|
u8 Rate;
|
||||||
|
@ -80,6 +83,10 @@ u32 RXCounter;
|
||||||
|
|
||||||
int MPReplyTimer;
|
int MPReplyTimer;
|
||||||
int MPNumReplies;
|
int MPNumReplies;
|
||||||
|
int MPReplyFrame; // for client
|
||||||
|
u8 MPHostMAC[6];
|
||||||
|
u8 MPHostBSS[6];
|
||||||
|
u16 MPHostSeqNo;
|
||||||
|
|
||||||
bool MPInited;
|
bool MPInited;
|
||||||
bool LANInited;
|
bool LANInited;
|
||||||
|
@ -87,6 +94,13 @@ bool LANInited;
|
||||||
int USUntilPowerOn;
|
int USUntilPowerOn;
|
||||||
bool ForcePowerOn;
|
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:
|
// multiplayer host TX sequence:
|
||||||
// 1. preamble
|
// 1. preamble
|
||||||
// 2. IRQ7
|
// 2. IRQ7
|
||||||
|
@ -204,15 +218,25 @@ void Reset()
|
||||||
USCompare = 0;
|
USCompare = 0;
|
||||||
BlockBeaconIRQ14 = false;
|
BlockBeaconIRQ14 = false;
|
||||||
|
|
||||||
|
memset(TXSlots, 0, sizeof(TXSlots));
|
||||||
ComStatus = 0;
|
ComStatus = 0;
|
||||||
TXCurSlot = -1;
|
TXCurSlot = -1;
|
||||||
RXCounter = 0;
|
RXCounter = 0;
|
||||||
|
|
||||||
MPReplyTimer = 0;
|
MPReplyTimer = 0;
|
||||||
MPNumReplies = 0;
|
MPNumReplies = 0;
|
||||||
|
MPReplyFrame = 0;
|
||||||
|
memset(MPHostMAC, 0, 6);
|
||||||
|
memset(MPHostBSS, 0, 6);
|
||||||
|
MPHostSeqNo = 0;
|
||||||
|
|
||||||
CmdCounter = 0;
|
CmdCounter = 0;
|
||||||
|
|
||||||
|
IsMPClient = false;
|
||||||
|
TimeOffsetToHost = 0;
|
||||||
|
NextSync = 0;
|
||||||
|
SyncBack = false;
|
||||||
|
|
||||||
WifiAP::Reset();
|
WifiAP::Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +342,7 @@ void SetIRQ15()
|
||||||
|
|
||||||
void SetStatus(u32 status)
|
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};
|
u16 rfpins[10] = {0x04, 0x84, 0, 0x46, 0, 0x84, 0x87, 0, 0x46, 0x04};
|
||||||
IOPORT(W_RFStatus) = status;
|
IOPORT(W_RFStatus) = status;
|
||||||
IOPORT(W_RFPins) = rfpins[status];
|
IOPORT(W_RFPins) = rfpins[status];
|
||||||
|
@ -331,8 +355,6 @@ bool MACEqual(u8* a, u8* b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: set RFSTATUS/RFPINS
|
|
||||||
|
|
||||||
int PreambleLen(int rate)
|
int PreambleLen(int rate)
|
||||||
{
|
{
|
||||||
if (rate == 1) return 192;
|
if (rate == 1) return 192;
|
||||||
|
@ -340,6 +362,16 @@ int PreambleLen(int rate)
|
||||||
return 192;
|
return 192;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 NumClients(u16 bitmask)
|
||||||
|
{
|
||||||
|
u32 ret = 0;
|
||||||
|
for (int i = 1; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (bitmask & (1<<i)) ret++;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
void IncrementTXCount(TXSlot* slot)
|
void IncrementTXCount(TXSlot* slot)
|
||||||
{
|
{
|
||||||
u8 cnt = RAM[slot->Addr + 0x4];
|
u8 cnt = RAM[slot->Addr + 0x4];
|
||||||
|
@ -371,7 +403,7 @@ void StartTX_Cmd()
|
||||||
|
|
||||||
// TODO: cancel the transfer if there isn't enough time left (check CMDCOUNT)
|
// 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->Addr = (IOPORT(W_TXSlotCmd) & 0x0FFF) << 1;
|
||||||
slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF;
|
slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF;
|
||||||
|
@ -442,25 +474,60 @@ void FireTX()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
u16 vogon = 0x1312;
|
||||||
|
|
||||||
void SendMPReply(u16 clienttime, u16 clientmask)
|
void SendMPReply(u16 clienttime, u16 clientmask)
|
||||||
{
|
{
|
||||||
TXSlot* slot = &TXSlots[5];
|
TXSlot* slot = &TXSlots[5];
|
||||||
|
|
||||||
|
vogon = *(u16*)&RXBuffer[0xC + 22]; // seqno
|
||||||
|
|
||||||
// mark the last packet as success. dunno what the MSB is, it changes.
|
// mark the last packet as success. dunno what the MSB is, it changes.
|
||||||
|
//if (slot->Valid)
|
||||||
if (IOPORT(W_TXSlotReply2) & 0x8000)
|
if (IOPORT(W_TXSlotReply2) & 0x8000)
|
||||||
*(u16*)&RAM[slot->Addr] = 0x0001;
|
*(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_TXSlotReply2) = IOPORT(W_TXSlotReply1);
|
||||||
IOPORT(W_TXSlotReply1) = 0;
|
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
|
// 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)
|
// 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;
|
//*(u16*)&RAM[slot->Addr + 0x4] = 0x0001;
|
||||||
IncrementTXCount(slot);
|
IncrementTXCount(slot);
|
||||||
|
|
||||||
|
slot->CurPhase = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
slot->CurPhase = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 clientnum = 0;
|
u16 clientnum = 0;
|
||||||
|
@ -470,8 +537,20 @@ void SendMPReply(u16 clienttime, u16 clientmask)
|
||||||
clientnum++;
|
clientnum++;
|
||||||
}
|
}
|
||||||
|
|
||||||
slot->CurPhase = 0;
|
slot->CurPhaseTime = 16 + ((clienttime + 10) * clientnum) + PreambleLen(slot->Rate);
|
||||||
slot->CurPhaseTime = 16 + ((clienttime + 10) * clientnum);
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@ -488,6 +567,8 @@ void SendMPDefaultReply()
|
||||||
// TODO
|
// TODO
|
||||||
reply[0x8] = 0x14;
|
reply[0x8] = 0x14;
|
||||||
|
|
||||||
|
*(u16*)&reply[0x6] = vogon;
|
||||||
|
|
||||||
*(u16*)&reply[0xC + 0x00] = 0x0158;
|
*(u16*)&reply[0xC + 0x00] = 0x0158;
|
||||||
*(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO??
|
*(u16*)&reply[0xC + 0x02] = 0x00F0;//0; // TODO??
|
||||||
*(u16*)&reply[0xC + 0x04] = IOPORT(W_BSSID0);
|
*(u16*)&reply[0xC + 0x04] = IOPORT(W_BSSID0);
|
||||||
|
@ -529,21 +610,42 @@ 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;
|
*(u16*)&ack[0xC + 0x1A] = 0; // TODO: bitmask of which clients failed to reply
|
||||||
*(u32*)&ack[0xC + 0x1C] = 0;
|
*(u32*)&ack[0xC + 0x1C] = 0;
|
||||||
|
|
||||||
int txlen = Platform::MP_SendPacket(ack, 12+32);
|
int txlen = Platform::MP_SendPacket(ack, 12+32);
|
||||||
WIFI_LOG("wifi: sent %d/44 bytes of MP ack, %d %d\n", txlen, ComStatus, RXTime);
|
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;
|
*(u16*)&RXBuffer[0xA] = 32; // length
|
||||||
for (int i = 1; i < 16; i++)
|
|
||||||
{
|
// rate
|
||||||
if (bitmask & (1<<i)) ret++;
|
//if (TXSlots[1].Rate == 2) RXBuffer[0x8] = 0x14;
|
||||||
}
|
//else RXBuffer[0x8] = 0xA;
|
||||||
return ret;
|
RXBuffer[0x8] = 0x14; // FIXME!!!
|
||||||
|
|
||||||
|
printf("CLIENT MP ACK:\n");
|
||||||
|
PRINT_MAC("-MAC: ", MPHostMAC);
|
||||||
|
PRINT_MAC("-BSS: ", MPHostBSS);
|
||||||
|
printf("-SeqNo: %04X\n", MPHostSeqNo+0x10);
|
||||||
|
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x00] = 0x0218;
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x02] = 0;
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x04] = 0x0903;
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x06] = 0x00BF;
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x08] = 0x0300;
|
||||||
|
memcpy(&RXBuffer[0xC + 0x0A], MPHostBSS, 6);
|
||||||
|
memcpy(&RXBuffer[0xC + 0x10], MPHostMAC, 6);
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x16] = (MPHostSeqNo & 0xFFF0) + 0x10;
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x18] = 0x0033; // ???
|
||||||
|
*(u16*)&RXBuffer[0xC + 0x1A] = 0;
|
||||||
|
*(u32*)&RXBuffer[0xC + 0x1C] = 0;
|
||||||
|
|
||||||
|
FakeRX();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckRX(bool block);
|
bool CheckRX(bool block);
|
||||||
|
@ -566,7 +668,27 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
if (CheckRX(true))
|
if (CheckRX(true))
|
||||||
{
|
{
|
||||||
ComStatus |= 0x1;
|
ComStatus |= 0x1;
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
// TODO: properly handle reply errors
|
// TODO: properly handle reply errors
|
||||||
// also, if the reply is too big to fit within its window, what happens?
|
// 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);
|
SetStatus(8);
|
||||||
|
|
||||||
// if no reply is configured, send a default empty reply
|
//slot->Addr = (IOPORT(W_TXSlotReply2) & 0x0FFF) << 1;
|
||||||
if (!(IOPORT(W_TXSlotReply2) & 0x8000))
|
//slot->Length = *(u16*)&RAM[slot->Addr + 0xA] & 0x3FFF;
|
||||||
{
|
|
||||||
SendMPDefaultReply();
|
|
||||||
|
|
||||||
slot->Addr = 0;
|
/*u8 rate = RAM[slot->Addr + 0x8];
|
||||||
slot->Length = 28;
|
if (rate == 0x14) slot->Rate = 2;
|
||||||
slot->Rate = 2; // TODO
|
else slot->Rate = 1;*/
|
||||||
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;
|
|
||||||
|
|
||||||
// TODO: duration should be set by hardware
|
// TODO: duration should be set by hardware
|
||||||
// doesn't seem to be important
|
// doesn't seem to be important
|
||||||
//RAM[slot->Addr + 0xC + 2] = 0x00F0;
|
//RAM[slot->Addr + 0xC + 2] = 0x00F0;
|
||||||
|
|
||||||
u8 rate = RAM[slot->Addr + 0x8];
|
|
||||||
if (rate == 0x14) slot->Rate = 2;
|
|
||||||
else slot->Rate = 1;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SetStatus(3);
|
SetStatus(3);
|
||||||
|
@ -644,10 +751,27 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
*(u64*)&RAM[slot->Addr + 0xC + 24] = USCounter;
|
*(u64*)&RAM[slot->Addr + 0xC + 24] = USCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
//u32 noseqno = 0;
|
/*if (slot->Length==34)
|
||||||
//if (num == 1) noseqno = (IOPORT(W_TXSlotCmd) & 0x4000);
|
{
|
||||||
|
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;
|
*(u16*)&RAM[slot->Addr + 0xC + 22] = IOPORT(W_TXSeqNo) << 4;
|
||||||
IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF;
|
IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF;
|
||||||
|
@ -656,16 +780,75 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
// set TX addr
|
// set TX addr
|
||||||
IOPORT(W_RXTXAddr) = slot->Addr >> 1;
|
IOPORT(W_RXTXAddr) = slot->Addr >> 1;
|
||||||
|
|
||||||
// send
|
if (num == 1)
|
||||||
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",
|
// make sure the clients are synced up
|
||||||
txlen, slot->Length+12, num, slot->Addr, *(u16*)&RAM[slot->Addr + 0xC],
|
// TODO!!!! this should be for all currently connected clients regardless of the clientmask in the packet
|
||||||
*(u16*)&RAM[slot->Addr + 0x24], *(u16*)&RAM[slot->Addr + 0x26]);
|
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
|
// 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
|
// 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)
|
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);
|
WifiAP::SendPacket(&RAM[slot->Addr], 12 + slot->Length);
|
||||||
|
}
|
||||||
|
|
||||||
if (num == 4)
|
if (num == 4)
|
||||||
{
|
{
|
||||||
|
@ -674,6 +857,21 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
}
|
}
|
||||||
break;
|
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
|
case 1: // transmit done
|
||||||
{
|
{
|
||||||
// for the MP reply slot, this is set later
|
// 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];
|
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2];
|
||||||
MPNumReplies = NumClients(clientmask);
|
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->CurPhase = 2;
|
||||||
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * MPNumReplies);
|
slot->CurPhaseTime = 112 + ((10 + IOPORT(W_CmdReplyTime)) * MPNumReplies);
|
||||||
|
|
||||||
|
@ -711,6 +911,11 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
IOPORT(W_TXBusy) &= ~0x80;
|
IOPORT(W_TXBusy) &= ~0x80;
|
||||||
FireTX();
|
FireTX();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
/*slot->CurPhase = 5;
|
||||||
|
slot->CurPhaseTime = MPReplyFrame;
|
||||||
|
|
||||||
|
break;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
IOPORT(W_TXBusy) &= ~(1<<num);
|
IOPORT(W_TXBusy) &= ~(1<<num);
|
||||||
|
@ -750,8 +955,26 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
if (slot->Rate == 2) slot->CurPhaseTime = 32 * 4;
|
if (slot->Rate == 2) slot->CurPhaseTime = 32 * 4;
|
||||||
else slot->CurPhaseTime = 32 * 8;
|
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();
|
SendMPAck();
|
||||||
|
|
||||||
|
// send further sync
|
||||||
|
Platform::MP_SendSync(/*clientmask*/0x0002, 1, USCounter + slot->CurPhaseTime);
|
||||||
|
|
||||||
slot->CurPhase = 3;
|
slot->CurPhase = 3;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -767,7 +990,11 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
IncrementTXCount(slot);
|
IncrementTXCount(slot);
|
||||||
|
|
||||||
SetIRQ(12);
|
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)
|
||||||
{
|
{
|
||||||
|
@ -776,17 +1003,37 @@ bool ProcessTX(TXSlot* slot, int num)
|
||||||
}
|
}
|
||||||
SetStatus(1);
|
SetStatus(1);
|
||||||
|
|
||||||
|
// let clients run ahead some
|
||||||
|
u16 clientmask = *(u16*)&RAM[slot->Addr + 12 + 24 + 2];
|
||||||
|
//Platform::MP_SendSync(clientmask, 1, kMaxRunahead);
|
||||||
|
|
||||||
FireTX();
|
FireTX();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case 4: // MP default reply transfer finished
|
case 4: // MP default reply transfer finished
|
||||||
{
|
{
|
||||||
|
IOPORT(W_TXSeqNo) = (IOPORT(W_TXSeqNo) + 1) & 0x0FFF;
|
||||||
|
|
||||||
IOPORT(W_TXBusy) &= ~0x80;
|
IOPORT(W_TXBusy) &= ~0x80;
|
||||||
SetStatus(1);
|
SetStatus(1);
|
||||||
FireTX();
|
FireTX();
|
||||||
}
|
}
|
||||||
return true;
|
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;
|
return false;
|
||||||
|
@ -803,7 +1050,7 @@ inline void IncrementRXAddr(u16& addr, u16 inc = 2)
|
||||||
addr = (IOPORT(W_RXBufBegin) & 0x1FFE);
|
addr = (IOPORT(W_RXBufBegin) & 0x1FFE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
u16 zarp = 0;
|
||||||
bool CheckRX(bool block)
|
bool CheckRX(bool block)
|
||||||
{
|
{
|
||||||
if (!(IOPORT(W_RXCnt) & 0x8000))
|
if (!(IOPORT(W_RXCnt) & 0x8000))
|
||||||
|
@ -894,6 +1141,12 @@ bool CheckRX(bool block)
|
||||||
!(RXBuffer[12 + a_dst] & 0x01))
|
!(RXBuffer[12 + a_dst] & 0x01))
|
||||||
{
|
{
|
||||||
printf("received packet %04X but it didn't pass the MAC check\n", framectl);
|
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;
|
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",
|
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",
|
||||||
|
// 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
|
// make RX header
|
||||||
|
|
||||||
|
@ -993,6 +1395,51 @@ void USTimer(u32 param)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!uspart) MSTimer();
|
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)
|
if (IOPORT(W_CmdCountCnt) & 0x0001)
|
||||||
|
@ -1091,11 +1538,20 @@ void USTimer(u32 param)
|
||||||
|
|
||||||
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))))
|
||||||
{
|
{
|
||||||
SendMPReply(*(u16*)&RXBuffer[0xC + 24], *(u16*)&RXBuffer[0xC + 26]);
|
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);
|
//printf("WIFI: read %08X\n", addr);
|
||||||
if (addr >= 0x4000 && addr < 0x6000)
|
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];
|
return *(u16*)&RAM[addr & 0x1FFE];
|
||||||
}
|
}
|
||||||
if (addr >= 0x2000 && addr < 0x4000)
|
if (addr >= 0x2000 && addr < 0x4000)
|
||||||
|
@ -1214,6 +1679,8 @@ u16 Read(u32 addr)
|
||||||
{
|
{
|
||||||
u32 rdaddr = IOPORT(W_RXBufReadAddr);
|
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];
|
u16 ret = *(u16*)&RAM[rdaddr];
|
||||||
|
|
||||||
rdaddr += 2;
|
rdaddr += 2;
|
||||||
|
@ -1454,7 +1921,7 @@ void Write(u32 addr, u16 val)
|
||||||
case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return;
|
case W_USCompare2: USCompare = (USCompare & 0xFFFF0000FFFFFFFF) | ((u64)val << 32); return;
|
||||||
case W_USCompare3: USCompare = (USCompare & 0x0000FFFFFFFFFFFF) | ((u64)val << 48); 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:
|
case W_BBCnt:
|
||||||
IOPORT(W_BBCnt) = val;
|
IOPORT(W_BBCnt) = val;
|
||||||
|
@ -1570,6 +2037,7 @@ void Write(u32 addr, u16 val)
|
||||||
case W_TXSlotCmd:
|
case W_TXSlotCmd:
|
||||||
// checkme: is it possible to cancel a queued transfer that hasn't started yet
|
// checkme: is it possible to cancel a queued transfer that hasn't started yet
|
||||||
// by clearing bit15 here?
|
// by clearing bit15 here?
|
||||||
|
// TODO: "W_TXBUF_CMD.Bit15 can be set ONLY while W_CMD_COUNT is non-zero."
|
||||||
IOPORT(addr&0xFFF) = val;
|
IOPORT(addr&0xFFF) = val;
|
||||||
FireTX();
|
FireTX();
|
||||||
return;
|
return;
|
||||||
|
@ -1598,6 +2066,10 @@ void Write(u32 addr, u16 val)
|
||||||
case 0x268:
|
case 0x268:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
case W_RXFilter:
|
||||||
|
//printf("wifi: stupid RX filter=%04X\n", val);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
//printf("WIFI unk: write %08X %04X\n", addr, val);
|
//printf("WIFI unk: write %08X %04X\n", addr, val);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -55,6 +55,7 @@
|
||||||
#include "ROMManager.h"
|
#include "ROMManager.h"
|
||||||
#include "LAN_Socket.h"
|
#include "LAN_Socket.h"
|
||||||
#include "LAN_PCap.h"
|
#include "LAN_PCap.h"
|
||||||
|
#include "SPI.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#ifndef INVALID_SOCKET
|
#ifndef INVALID_SOCKET
|
||||||
|
@ -65,16 +66,17 @@
|
||||||
std::string EmuDirectory;
|
std::string EmuDirectory;
|
||||||
|
|
||||||
void emuStop();
|
void emuStop();
|
||||||
|
extern u16 zanf;
|
||||||
|
|
||||||
namespace Platform
|
namespace Platform
|
||||||
{
|
{
|
||||||
|
|
||||||
socket_t MPSocket;
|
u32 MPUniqueID;
|
||||||
sockaddr_t MPSendAddr;
|
socket_t MPSocket[2];
|
||||||
|
sockaddr_t MPSendAddr[2];
|
||||||
u8 PacketBuffer[2048];
|
u8 PacketBuffer[2048];
|
||||||
|
|
||||||
#define NIFI_VER 1
|
#define NIFI_VER 2
|
||||||
|
|
||||||
|
|
||||||
void Init(int argc, char** argv)
|
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()
|
bool MP_Init()
|
||||||
{
|
{
|
||||||
int opt_true = 1;
|
int opt_true = 1;
|
||||||
int res;
|
int res0, res1;
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
WSADATA wsadata;
|
WSADATA wsadata;
|
||||||
|
@ -399,26 +429,40 @@ bool MP_Init()
|
||||||
}
|
}
|
||||||
#endif // __WIN32__
|
#endif // __WIN32__
|
||||||
|
|
||||||
MPSocket = socket(AF_INET, SOCK_DGRAM, 0);
|
MPSocket[0] = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (MPSocket < 0)
|
if (MPSocket[0] < 0)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt_true, sizeof(int));
|
MPSocket[1] = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
if (res < 0)
|
if (MPSocket[1] < 0)
|
||||||
{
|
{
|
||||||
closesocket(MPSocket);
|
closesocket(MPSocket[0]);
|
||||||
MPSocket = INVALID_SOCKET;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BSD) || defined(__APPLE__)
|
#if defined(BSD) || defined(__APPLE__)
|
||||||
res = setsockopt(MPSocket, SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
|
res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
|
||||||
if (res < 0)
|
res0 = setsockopt(MPSocket[1], SOL_SOCKET, SO_REUSEPORT, (const char*)&opt_true, sizeof(int));
|
||||||
|
if (res0 < 0 || res1 < 0)
|
||||||
{
|
{
|
||||||
closesocket(MPSocket);
|
closesocket(MPSocket[0]);
|
||||||
MPSocket = INVALID_SOCKET;
|
MPSocket[0] = INVALID_SOCKET;
|
||||||
|
closesocket(MPSocket[1]);
|
||||||
|
MPSocket[1] = INVALID_SOCKET;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -427,33 +471,51 @@ bool MP_Init()
|
||||||
saddr.sa_family = AF_INET;
|
saddr.sa_family = AF_INET;
|
||||||
*(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK);
|
*(u32*)&saddr.sa_data[2] = htonl(Config::SocketBindAnyAddr ? INADDR_ANY : INADDR_LOOPBACK);
|
||||||
*(u16*)&saddr.sa_data[0] = htons(7064);
|
*(u16*)&saddr.sa_data[0] = htons(7064);
|
||||||
res = bind(MPSocket, &saddr, sizeof(sockaddr_t));
|
res0 = bind(MPSocket[0], &saddr, sizeof(sockaddr_t));
|
||||||
if (res < 0)
|
*(u16*)&saddr.sa_data[0] = htons(7065);
|
||||||
|
res1 = bind(MPSocket[1], &saddr, sizeof(sockaddr_t));
|
||||||
|
if (res0 < 0 || res1 < 0)
|
||||||
{
|
{
|
||||||
closesocket(MPSocket);
|
closesocket(MPSocket[0]);
|
||||||
MPSocket = INVALID_SOCKET;
|
MPSocket[0] = INVALID_SOCKET;
|
||||||
|
closesocket(MPSocket[1]);
|
||||||
|
MPSocket[1] = INVALID_SOCKET;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = setsockopt(MPSocket, SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
|
res0 = setsockopt(MPSocket[0], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
|
||||||
if (res < 0)
|
res1 = setsockopt(MPSocket[1], SOL_SOCKET, SO_BROADCAST, (const char*)&opt_true, sizeof(int));
|
||||||
|
if (res0 < 0 || res1 < 0)
|
||||||
{
|
{
|
||||||
closesocket(MPSocket);
|
closesocket(MPSocket[0]);
|
||||||
MPSocket = INVALID_SOCKET;
|
MPSocket[0] = INVALID_SOCKET;
|
||||||
|
closesocket(MPSocket[1]);
|
||||||
|
MPSocket[1] = INVALID_SOCKET;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MPSendAddr.sa_family = AF_INET;
|
MPSendAddr[0].sa_family = AF_INET;
|
||||||
*(u32*)&MPSendAddr.sa_data[2] = htonl(INADDR_BROADCAST);
|
*(u32*)&MPSendAddr[0].sa_data[2] = htonl(INADDR_BROADCAST);
|
||||||
*(u16*)&MPSendAddr.sa_data[0] = htons(7064);
|
*(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP_DeInit()
|
void MP_DeInit()
|
||||||
{
|
{
|
||||||
if (MPSocket >= 0)
|
if (MPSocket[0] >= 0)
|
||||||
closesocket(MPSocket);
|
closesocket(MPSocket[0]);
|
||||||
|
if (MPSocket[1] >= 0)
|
||||||
|
closesocket(MPSocket[1]);
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
@ -462,10 +524,10 @@ void MP_DeInit()
|
||||||
|
|
||||||
int MP_SendPacket(u8* data, int len)
|
int MP_SendPacket(u8* data, int len)
|
||||||
{
|
{
|
||||||
if (MPSocket < 0)
|
if (MPSocket[0] < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (len > 2048-8)
|
if (len > 2048-12)
|
||||||
{
|
{
|
||||||
printf("MP_SendPacket: error: packet too long (%d)\n", len);
|
printf("MP_SendPacket: error: packet too long (%d)\n", len);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -475,57 +537,216 @@ int MP_SendPacket(u8* data, int len)
|
||||||
PacketBuffer[4] = NIFI_VER;
|
PacketBuffer[4] = NIFI_VER;
|
||||||
PacketBuffer[5] = 0;
|
PacketBuffer[5] = 0;
|
||||||
*(u16*)&PacketBuffer[6] = htons(len);
|
*(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));
|
_logpacket(true, data, len);
|
||||||
if (slen < 8) return 0;
|
|
||||||
return slen - 8;
|
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)
|
int MP_RecvPacket(u8* data, bool block)
|
||||||
{
|
{
|
||||||
if (MPSocket < 0)
|
if (MPSocket[0] < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fd_set fd;
|
fd_set fd;
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
|
|
||||||
FD_ZERO(&fd);
|
for (;;)
|
||||||
FD_SET(MPSocket, &fd);
|
|
||||||
tv.tv_sec = 0;
|
|
||||||
tv.tv_usec = block ? 5000 : 0;
|
|
||||||
|
|
||||||
if (!select(MPSocket+1, &fd, 0, 0, &tv))
|
|
||||||
{
|
{
|
||||||
|
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;
|
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;
|
return clientmask;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <QProcess>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
|
@ -1475,6 +1476,11 @@ MainWindow::MainWindow(QWidget* parent) : QMainWindow(parent)
|
||||||
|
|
||||||
actTitleManager = menu->addAction("Manage DSi titles");
|
actTitleManager = menu->addAction("Manage DSi titles");
|
||||||
connect(actTitleManager, &QAction::triggered, this, &MainWindow::onOpenTitleManager);
|
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");
|
QMenu* menu = menubar->addMenu("Config");
|
||||||
|
@ -1828,7 +1834,7 @@ void MainWindow::keyPressEvent(QKeyEvent* event)
|
||||||
if (event->isAutoRepeat()) return;
|
if (event->isAutoRepeat()) return;
|
||||||
|
|
||||||
// TODO!! REMOVE ME IN RELEASE BUILDS!!
|
// 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);
|
Input::KeyPress(event);
|
||||||
}
|
}
|
||||||
|
@ -2602,6 +2608,17 @@ void MainWindow::onOpenTitleManager()
|
||||||
TitleManagerDialog* dlg = TitleManagerDialog::openDlg(this);
|
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()
|
void MainWindow::onOpenEmuSettings()
|
||||||
{
|
{
|
||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
|
@ -3180,12 +3197,13 @@ int CALLBACK WinMain(HINSTANCE hinst, HINSTANCE hprev, LPSTR cmdline, int cmdsho
|
||||||
|
|
||||||
if (argv_w) LocalFree(argv_w);
|
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", stdout);
|
||||||
freopen("CONOUT$", "w", stderr);
|
freopen("CONOUT$", "w", stderr);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}*/
|
}
|
||||||
|
|
||||||
int ret = main(argc, argv);
|
int ret = main(argc, argv);
|
||||||
|
|
||||||
|
|
|
@ -255,6 +255,7 @@ private slots:
|
||||||
void onROMInfo();
|
void onROMInfo();
|
||||||
void onRAMInfo();
|
void onRAMInfo();
|
||||||
void onOpenTitleManager();
|
void onOpenTitleManager();
|
||||||
|
void onTest();
|
||||||
|
|
||||||
void onOpenEmuSettings();
|
void onOpenEmuSettings();
|
||||||
void onEmuSettingsDialogFinished(int res);
|
void onEmuSettingsDialogFinished(int res);
|
||||||
|
@ -344,6 +345,7 @@ public:
|
||||||
QAction* actROMInfo;
|
QAction* actROMInfo;
|
||||||
QAction* actRAMInfo;
|
QAction* actRAMInfo;
|
||||||
QAction* actTitleManager;
|
QAction* actTitleManager;
|
||||||
|
QAction* actTest;
|
||||||
|
|
||||||
QAction* actEmuSettings;
|
QAction* actEmuSettings;
|
||||||
QAction* actPowerManagement;
|
QAction* actPowerManagement;
|
||||||
|
|
Loading…
Reference in New Issue