fix up LocalMP

This commit is contained in:
Arisotura
2024-06-05 00:10:12 +02:00
parent 153f01ec54
commit 15bb45d069
5 changed files with 148 additions and 333 deletions

View File

@ -38,6 +38,7 @@
#include "EmuInstance.h" #include "EmuInstance.h"
#include "Config.h" #include "Config.h"
#include "Platform.h" #include "Platform.h"
#include "LocalMP.h"
#include "NDS.h" #include "NDS.h"
#include "DSi.h" #include "DSi.h"
@ -99,6 +100,8 @@ EmuInstance::~EmuInstance()
{ {
// TODO window cleanup and shit? // TODO window cleanup and shit?
LocalMP::End(instanceID);
emuThread->emuExit(); emuThread->emuExit();
emuThread->wait(); emuThread->wait();
delete emuThread; delete emuThread;

View File

@ -33,6 +33,8 @@
#include <string> #include <string>
#include <QSharedMemory> #include <QSharedMemory>
#include <QMutex>
#include <QSemaphore>
#include "Config.h" #include "Config.h"
#include "LocalMP.h" #include "LocalMP.h"
@ -47,17 +49,12 @@ using Platform::LogLevel;
namespace LocalMP namespace LocalMP
{ {
u32 MPUniqueID; struct MPStatusData
u8 PacketBuffer[2048];
struct MPQueueHeader
{ {
u16 NumInstances;
u16 InstanceBitmask; // bitmask of all instances present
u16 ConnectedBitmask; // bitmask of which instances are ready to send/receive packets u16 ConnectedBitmask; // bitmask of which instances are ready to send/receive packets
u32 PacketWriteOffset; u32 PacketWriteOffset;
u32 ReplyWriteOffset; u32 ReplyWriteOffset;
u16 MPHostInstanceID; // instance ID from which the last CMD frame was sent u16 MPHostinst; // instance ID from which the last CMD frame was sent
u16 MPReplyBitmask; // bitmask of which clients replied in time u16 MPReplyBitmask; // bitmask of which clients replied in time
}; };
@ -70,23 +67,15 @@ struct MPPacketHeader
u64 Timestamp; u64 Timestamp;
}; };
struct MPSync QMutex MPQueueLock;
{ MPStatusData MPStatus;
u32 Magic; u8* MPQueue = nullptr;
u32 SenderID; u32 PacketReadOffset[16];
u16 ClientMask; u32 ReplyReadOffset[16];
u16 Type;
u64 Timestamp;
};
QSharedMemory* MPQueue;
int InstanceID;
u32 PacketReadOffset;
u32 ReplyReadOffset;
const u32 kQueueSize = 0x20000; const u32 kQueueSize = 0x20000;
const u32 kMaxFrameSize = 0x800; const u32 kMaxFrameSize = 0x800;
const u32 kPacketStart = sizeof(MPQueueHeader); const u32 kPacketStart = 0;
const u32 kReplyStart = kQueueSize / 2; const u32 kReplyStart = kQueueSize / 2;
const u32 kPacketEnd = kReplyStart; const u32 kPacketEnd = kReplyStart;
const u32 kReplyEnd = kQueueSize; const u32 kReplyEnd = kQueueSize;
@ -96,204 +85,57 @@ int RecvTimeout;
int LastHostID; int LastHostID;
// we need to come up with our own abstraction layer for named semaphores QSemaphore SemPool[32];
// because QSystemSemaphore doesn't support waiting with a timeout
// and, as such, is unsuitable to our needs
#ifdef __WIN32__
bool SemInited[32];
HANDLE SemPool[32];
void SemPoolInit() void SemPoolInit()
{ {
for (int i = 0; i < 32; i++) for (int i = 0; i < 32; i++)
{ {
SemPool[i] = INVALID_HANDLE_VALUE; SemPool[i].acquire(SemPool[i].available());
SemInited[i] = false;
} }
} }
void SemDeinit(int num);
void SemPoolDeinit()
{
for (int i = 0; i < 32; i++)
SemDeinit(i);
}
bool SemInit(int num)
{
if (SemInited[num])
return true;
char semname[64];
sprintf(semname, "Local\\melonNIFI_Sem%02d", num);
HANDLE sem = CreateSemaphoreA(nullptr, 0, 64, semname);
SemPool[num] = sem;
SemInited[num] = true;
return sem != INVALID_HANDLE_VALUE;
}
void SemDeinit(int num)
{
if (SemPool[num] != INVALID_HANDLE_VALUE)
{
CloseHandle(SemPool[num]);
SemPool[num] = INVALID_HANDLE_VALUE;
}
SemInited[num] = false;
}
bool SemPost(int num) bool SemPost(int num)
{ {
SemInit(num); SemPool[num].release(1);
return ReleaseSemaphore(SemPool[num], 1, nullptr) != 0; return true;
}
bool SemWait(int num, int timeout)
{
return WaitForSingleObject(SemPool[num], timeout) == WAIT_OBJECT_0;
}
void SemReset(int num)
{
while (WaitForSingleObject(SemPool[num], 0) == WAIT_OBJECT_0);
}
#else
bool SemInited[32];
sem_t* SemPool[32];
void SemPoolInit()
{
for (int i = 0; i < 32; i++)
{
SemPool[i] = SEM_FAILED;
SemInited[i] = false;
}
}
void SemDeinit(int num);
void SemPoolDeinit()
{
for (int i = 0; i < 32; i++)
SemDeinit(i);
}
bool SemInit(int num)
{
if (SemInited[num])
return true;
char semname[64];
sprintf(semname, "/melonNIFI_Sem%02d", num);
sem_t* sem = sem_open(semname, O_CREAT, 0644, 0);
SemPool[num] = sem;
SemInited[num] = true;
return sem != SEM_FAILED;
}
void SemDeinit(int num)
{
if (SemPool[num] != SEM_FAILED)
{
sem_close(SemPool[num]);
SemPool[num] = SEM_FAILED;
}
SemInited[num] = false;
}
bool SemPost(int num)
{
SemInit(num);
return sem_post(SemPool[num]) == 0;
} }
bool SemWait(int num, int timeout) bool SemWait(int num, int timeout)
{ {
if (!timeout) if (!timeout)
return sem_trywait(SemPool[num]) == 0; return SemPool[num].tryAcquire(1);
struct timespec ts; return SemPool[num].tryAcquire(1, timeout);
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_nsec += timeout * 1000000;
long sec = ts.tv_nsec / 1000000000;
ts.tv_nsec -= sec * 1000000000;
ts.tv_sec += sec;
return sem_timedwait(SemPool[num], &ts) == 0;
} }
void SemReset(int num) void SemReset(int num)
{ {
while (sem_trywait(SemPool[num]) == 0); SemPool[num].acquire(SemPool[num].available());
} }
#endif
bool Init() bool Init()
{ {
MPQueue = new QSharedMemory("melonNIFI"); MPQueueLock.lock();
if (!MPQueue->attach()) MPQueue = new u8[kQueueSize];
{ memset(MPQueue, 0, kQueueSize);
Log(LogLevel::Info, "MP sharedmem doesn't exist. creating\n"); memset(&MPStatus, 0, sizeof(MPStatus));
if (!MPQueue->create(kQueueSize)) memset(PacketReadOffset, 0, sizeof(PacketReadOffset));
{ memset(ReplyReadOffset, 0, sizeof(ReplyReadOffset));
Log(LogLevel::Error, "MP sharedmem create failed :( (%d)\n", MPQueue->error());
delete MPQueue;
MPQueue = nullptr;
return false;
}
MPQueue->lock(); MPQueueLock.unlock();
memset(MPQueue->data(), 0, MPQueue->size());
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
header->PacketWriteOffset = kPacketStart;
header->ReplyWriteOffset = kReplyStart;
MPQueue->unlock();
}
MPQueue->lock();
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data();
u16 mask = header->InstanceBitmask;
for (int i = 0; i < 16; i++)
{
if (!(mask & (1<<i)))
{
InstanceID = i;
header->InstanceBitmask |= (1<<i);
//header->ConnectedBitmask |= (1 << i);
break;
}
}
header->NumInstances++;
PacketReadOffset = header->PacketWriteOffset;
ReplyReadOffset = header->ReplyWriteOffset;
MPQueue->unlock();
// prepare semaphores // prepare semaphores
// semaphores 0-15: regular frames; semaphore I is posted when instance I needs to process a new frame // semaphores 0-15: regular frames; semaphore I is posted when instance I needs to process a new frame
// semaphores 16-31: MP replies; semaphore I is posted when instance I needs to process a new MP reply // semaphores 16-31: MP replies; semaphore I is posted when instance I needs to process a new MP reply
SemPoolInit(); SemPoolInit();
SemInit(InstanceID);
SemInit(16+InstanceID);
LastHostID = -1; LastHostID = -1;
Log(LogLevel::Info, "MP comm init OK, instance ID %d\n", InstanceID); Log(LogLevel::Info, "MP comm init OK\n");
RecvTimeout = 25; RecvTimeout = 25;
@ -302,23 +144,6 @@ bool Init()
void DeInit() void DeInit()
{ {
if (MPQueue)
{
MPQueue->lock();
if (MPQueue->data() != nullptr)
{
MPQueueHeader *header = (MPQueueHeader *) MPQueue->data();
header->ConnectedBitmask &= ~(1 << InstanceID);
header->InstanceBitmask &= ~(1 << InstanceID);
header->NumInstances--;
}
MPQueue->unlock();
SemPoolDeinit();
MPQueue->detach();
}
delete MPQueue; delete MPQueue;
MPQueue = nullptr; MPQueue = nullptr;
} }
@ -328,44 +153,42 @@ void SetRecvTimeout(int timeout)
RecvTimeout = timeout; RecvTimeout = timeout;
} }
void Begin() void Begin(int inst)
{ {
if (!MPQueue) return; if (!MPQueue) return;
MPQueue->lock();
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data(); MPQueueLock.lock();
PacketReadOffset = header->PacketWriteOffset; PacketReadOffset[inst] = MPStatus.PacketWriteOffset;
ReplyReadOffset = header->ReplyWriteOffset; ReplyReadOffset[inst] = MPStatus.ReplyWriteOffset;
SemReset(InstanceID); SemReset(inst);
SemReset(16+InstanceID); SemReset(16+inst);
header->ConnectedBitmask |= (1 << InstanceID); MPStatus.ConnectedBitmask |= (1 << inst);
MPQueue->unlock(); MPQueueLock.unlock();
} }
void End() void End(int inst)
{ {
if (!MPQueue) return; if (!MPQueue) return;
MPQueue->lock();
MPQueueHeader* header = (MPQueueHeader*)MPQueue->data(); MPQueueLock.lock();
//SemReset(InstanceID); MPStatus.ConnectedBitmask &= ~(1 << inst);
//SemReset(16+InstanceID); MPQueueLock.unlock();
header->ConnectedBitmask &= ~(1 << InstanceID);
MPQueue->unlock();
} }
void FIFORead(int fifo, void* buf, int len) void FIFORead(int inst, int fifo, void* buf, int len)
{ {
u8* data = (u8*)MPQueue->data(); u8* data = MPQueue;
u32 offset, start, end; u32 offset, start, end;
if (fifo == 0) if (fifo == 0)
{ {
offset = PacketReadOffset; offset = PacketReadOffset[inst];
start = kPacketStart; start = kPacketStart;
end = kPacketEnd; end = kPacketEnd;
} }
else else
{ {
offset = ReplyReadOffset; offset = ReplyReadOffset[inst];
start = kReplyStart; start = kReplyStart;
end = kReplyEnd; end = kReplyEnd;
} }
@ -383,25 +206,24 @@ void FIFORead(int fifo, void* buf, int len)
offset += len; offset += len;
} }
if (fifo == 0) PacketReadOffset = offset; if (fifo == 0) PacketReadOffset[inst] = offset;
else ReplyReadOffset = offset; else ReplyReadOffset[inst] = offset;
} }
void FIFOWrite(int fifo, void* buf, int len) void FIFOWrite(int inst, int fifo, void* buf, int len)
{ {
u8* data = (u8*)MPQueue->data(); u8* data = MPQueue;
MPQueueHeader* header = (MPQueueHeader*)&data[0];
u32 offset, start, end; u32 offset, start, end;
if (fifo == 0) if (fifo == 0)
{ {
offset = header->PacketWriteOffset; offset = MPStatus.PacketWriteOffset;
start = kPacketStart; start = kPacketStart;
end = kPacketEnd; end = kPacketEnd;
} }
else else
{ {
offset = header->ReplyWriteOffset; offset = MPStatus.ReplyWriteOffset;
start = kReplyStart; start = kReplyStart;
end = kReplyEnd; end = kReplyEnd;
} }
@ -419,53 +241,51 @@ void FIFOWrite(int fifo, void* buf, int len)
offset += len; offset += len;
} }
if (fifo == 0) header->PacketWriteOffset = offset; if (fifo == 0) MPStatus.PacketWriteOffset = offset;
else header->ReplyWriteOffset = offset; else MPStatus.ReplyWriteOffset = offset;
} }
int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp) int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp)
{ {
if (!MPQueue) return 0; if (!MPQueue) return 0;
MPQueue->lock(); MPQueueLock.lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
u16 mask = header->ConnectedBitmask; u16 mask = MPStatus.ConnectedBitmask;
// TODO: check if the FIFO is full! // TODO: check if the FIFO is full!
MPPacketHeader pktheader; MPPacketHeader pktheader;
pktheader.Magic = 0x4946494E; pktheader.Magic = 0x4946494E;
pktheader.SenderID = InstanceID; pktheader.SenderID = inst;
pktheader.Type = type; pktheader.Type = type;
pktheader.Length = len; pktheader.Length = len;
pktheader.Timestamp = timestamp; pktheader.Timestamp = timestamp;
type &= 0xFFFF; type &= 0xFFFF;
int nfifo = (type == 2) ? 1 : 0; int nfifo = (type == 2) ? 1 : 0;
FIFOWrite(nfifo, &pktheader, sizeof(pktheader)); FIFOWrite(inst, nfifo, &pktheader, sizeof(pktheader));
if (len) if (len)
FIFOWrite(nfifo, packet, len); FIFOWrite(inst, nfifo, packet, len);
if (type == 1) if (type == 1)
{ {
// NOTE: this is not guarded against, say, multiple multiplay games happening on the same machine // NOTE: this is not guarded against, say, multiple multiplay games happening on the same machine
// we would need to pass the packet's SenderID through the wifi module for that // we would need to pass the packet's SenderID through the wifi module for that
header->MPHostInstanceID = InstanceID; MPStatus.MPHostinst = inst;
header->MPReplyBitmask = 0; MPStatus.MPReplyBitmask = 0;
ReplyReadOffset = header->ReplyWriteOffset; ReplyReadOffset[inst] = MPStatus.ReplyWriteOffset;
SemReset(16 + InstanceID); SemReset(16 + inst);
} }
else if (type == 2) else if (type == 2)
{ {
header->MPReplyBitmask |= (1 << InstanceID); MPStatus.MPReplyBitmask |= (1 << inst);
} }
MPQueue->unlock(); MPQueueLock.unlock();
if (type == 2) if (type == 2)
{ {
SemPost(16 + header->MPHostInstanceID); SemPost(16 + MPStatus.MPHostinst);
} }
else else
{ {
@ -479,84 +299,82 @@ int SendPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
return len; return len;
} }
int RecvPacketGeneric(u8* packet, bool block, u64* timestamp) int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp)
{ {
if (!MPQueue) return 0; if (!MPQueue) return 0;
for (;;) for (;;)
{ {
if (!SemWait(InstanceID, block ? RecvTimeout : 0)) if (!SemWait(inst, block ? RecvTimeout : 0))
{ {
return 0; return 0;
} }
MPQueue->lock(); MPQueueLock.lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
MPPacketHeader pktheader; MPPacketHeader pktheader;
FIFORead(0, &pktheader, sizeof(pktheader)); FIFORead(inst, 0, &pktheader, sizeof(pktheader));
if (pktheader.Magic != 0x4946494E) if (pktheader.Magic != 0x4946494E)
{ {
Log(LogLevel::Warn, "PACKET FIFO OVERFLOW\n"); Log(LogLevel::Warn, "PACKET FIFO OVERFLOW\n");
PacketReadOffset = header->PacketWriteOffset; PacketReadOffset[inst] = MPStatus.PacketWriteOffset;
SemReset(InstanceID); SemReset(inst);
MPQueue->unlock(); MPQueueLock.unlock();
return 0; return 0;
} }
if (pktheader.SenderID == InstanceID) if (pktheader.SenderID == inst)
{ {
// skip this packet // skip this packet
PacketReadOffset += pktheader.Length; PacketReadOffset[inst] += pktheader.Length;
if (PacketReadOffset >= kPacketEnd) if (PacketReadOffset[inst] >= kPacketEnd)
PacketReadOffset += kPacketStart - kPacketEnd; PacketReadOffset[inst] += kPacketStart - kPacketEnd;
MPQueue->unlock(); MPQueueLock.unlock();
continue; continue;
} }
if (pktheader.Length) if (pktheader.Length)
{ {
FIFORead(0, packet, pktheader.Length); FIFORead(inst, 0, packet, pktheader.Length);
if (pktheader.Type == 1) if (pktheader.Type == 1)
LastHostID = pktheader.SenderID; LastHostID = pktheader.SenderID;
} }
if (timestamp) *timestamp = pktheader.Timestamp; if (timestamp) *timestamp = pktheader.Timestamp;
MPQueue->unlock(); MPQueueLock.unlock();
return pktheader.Length; return pktheader.Length;
} }
} }
int SendPacket(u8* packet, int len, u64 timestamp) int SendPacket(int inst, u8* packet, int len, u64 timestamp)
{ {
return SendPacketGeneric(0, packet, len, timestamp); return SendPacketGeneric(inst, 0, packet, len, timestamp);
} }
int RecvPacket(u8* packet, u64* timestamp) int RecvPacket(int inst, u8* packet, u64* timestamp)
{ {
return RecvPacketGeneric(packet, false, timestamp); return RecvPacketGeneric(inst, packet, false, timestamp);
} }
int SendCmd(u8* packet, int len, u64 timestamp) int SendCmd(int inst, u8* packet, int len, u64 timestamp)
{ {
return SendPacketGeneric(1, packet, len, timestamp); return SendPacketGeneric(inst, 1, packet, len, timestamp);
} }
int SendReply(u8* packet, int len, u64 timestamp, u16 aid) int SendReply(int inst, u8* packet, int len, u64 timestamp, u16 aid)
{ {
return SendPacketGeneric(2 | (aid<<16), packet, len, timestamp); return SendPacketGeneric(inst, 2 | (aid<<16), packet, len, timestamp);
} }
int SendAck(u8* packet, int len, u64 timestamp) int SendAck(int inst, u8* packet, int len, u64 timestamp)
{ {
return SendPacketGeneric(3, packet, len, timestamp); return SendPacketGeneric(inst, 3, packet, len, timestamp);
} }
int RecvHostPacket(u8* packet, u64* timestamp) int RecvHostPacket(int inst, u8* packet, u64* timestamp)
{ {
if (!MPQueue) return -1; if (!MPQueue) return -1;
@ -564,33 +382,30 @@ int RecvHostPacket(u8* packet, u64* timestamp)
{ {
// check if the host is still connected // check if the host is still connected
MPQueue->lock(); MPQueueLock.lock();
u8* data = (u8*)MPQueue->data(); u8* data = MPQueue;
MPQueueHeader* header = (MPQueueHeader*)&data[0]; u16 curinstmask = MPStatus.ConnectedBitmask;
u16 curinstmask = header->ConnectedBitmask; MPQueueLock.unlock();
MPQueue->unlock();
if (!(curinstmask & (1 << LastHostID))) if (!(curinstmask & (1 << LastHostID)))
return -1; return -1;
} }
return RecvPacketGeneric(packet, true, timestamp); return RecvPacketGeneric(inst, packet, true, timestamp);
} }
u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask) u16 RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask)
{ {
if (!MPQueue) return 0; if (!MPQueue) return 0;
u16 ret = 0; u16 ret = 0;
u16 myinstmask = (1 << InstanceID); u16 myinstmask = (1 << inst);
u16 curinstmask; u16 curinstmask;
{ {
MPQueue->lock(); //MPQueueLock.lock();
u8* data = (u8*)MPQueue->data(); curinstmask = MPStatus.ConnectedBitmask;
MPQueueHeader* header = (MPQueueHeader*)&data[0]; //MPQueueLock.unlock();
curinstmask = header->ConnectedBitmask;
MPQueue->unlock();
} }
// if all clients have left: return early // if all clients have left: return early
@ -599,44 +414,42 @@ u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
for (;;) for (;;)
{ {
if (!SemWait(16+InstanceID, RecvTimeout)) if (!SemWait(16+inst, RecvTimeout))
{ {
// no more replies available // no more replies available
return ret; return ret;
} }
MPQueue->lock(); MPQueueLock.lock();
u8* data = (u8*)MPQueue->data();
MPQueueHeader* header = (MPQueueHeader*)&data[0];
MPPacketHeader pktheader; MPPacketHeader pktheader;
FIFORead(1, &pktheader, sizeof(pktheader)); FIFORead(inst, 1, &pktheader, sizeof(pktheader));
if (pktheader.Magic != 0x4946494E) if (pktheader.Magic != 0x4946494E)
{ {
Log(LogLevel::Warn, "REPLY FIFO OVERFLOW\n"); Log(LogLevel::Warn, "REPLY FIFO OVERFLOW\n");
ReplyReadOffset = header->ReplyWriteOffset; ReplyReadOffset[inst] = MPStatus.ReplyWriteOffset;
SemReset(16+InstanceID); SemReset(16+inst);
MPQueue->unlock(); MPQueueLock.unlock();
return 0; return 0;
} }
if ((pktheader.SenderID == InstanceID) || // packet we sent out (shouldn't happen, but hey) if ((pktheader.SenderID == inst) || // packet we sent out (shouldn't happen, but hey)
(pktheader.Timestamp < (timestamp - 32))) // stale packet (pktheader.Timestamp < (timestamp - 32))) // stale packet
{ {
// skip this packet // skip this packet
ReplyReadOffset += pktheader.Length; ReplyReadOffset[inst] += pktheader.Length;
if (ReplyReadOffset >= kReplyEnd) if (ReplyReadOffset[inst] >= kReplyEnd)
ReplyReadOffset += kReplyStart - kReplyEnd; ReplyReadOffset[inst] += kReplyStart - kReplyEnd;
MPQueue->unlock(); MPQueueLock.unlock();
continue; continue;
} }
if (pktheader.Length) if (pktheader.Length)
{ {
u32 aid = (pktheader.Type >> 16); u32 aid = (pktheader.Type >> 16);
FIFORead(1, &packets[(aid-1)*1024], pktheader.Length); FIFORead(inst, 1, &packets[(aid-1)*1024], pktheader.Length);
ret |= (1 << aid); ret |= (1 << aid);
} }
@ -646,11 +459,11 @@ u16 RecvReplies(u8* packets, u64 timestamp, u16 aidmask)
{ {
// all the clients have sent their reply // all the clients have sent their reply
MPQueue->unlock(); MPQueueLock.unlock();
return ret; return ret;
} }
MPQueue->unlock(); MPQueueLock.unlock();
} }
} }

View File

@ -30,16 +30,16 @@ void DeInit();
void SetRecvTimeout(int timeout); void SetRecvTimeout(int timeout);
void Begin(); void Begin(int inst);
void End(); void End(int inst);
int SendPacket(u8* data, int len, u64 timestamp); int SendPacket(int inst, u8* data, int len, u64 timestamp);
int RecvPacket(u8* data, u64* timestamp); int RecvPacket(int inst, u8* data, u64* timestamp);
int SendCmd(u8* data, int len, u64 timestamp); int SendCmd(int inst, u8* data, int len, u64 timestamp);
int SendReply(u8* data, int len, u64 timestamp, u16 aid); int SendReply(int inst, u8* data, int len, u64 timestamp, u16 aid);
int SendAck(u8* data, int len, u64 timestamp); int SendAck(int inst, u8* data, int len, u64 timestamp);
int RecvHostPacket(u8* data, u64* timestamp); int RecvHostPacket(int inst, u8* data, u64* timestamp);
u16 RecvReplies(u8* data, u64 timestamp, u16 aidmask); u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask);
} }

View File

@ -50,12 +50,6 @@
extern CameraManager* camManager[2]; extern CameraManager* camManager[2];
void emuStop();
// TEMP
//#include "main.h"
//extern MainWindow* mainWindow;
namespace melonDS::Platform namespace melonDS::Platform
{ {
@ -454,65 +448,65 @@ void WriteDateTime(int year, int month, int day, int hour, int minute, int secon
bool MP_Init(void* userdata) bool MP_Init(void* userdata)
{ {
//return LocalMP::Init();
return true; return true;
} }
void MP_DeInit(void* userdata) void MP_DeInit(void* userdata)
{ {
//return LocalMP::DeInit();
} }
void MP_Begin(void* userdata) void MP_Begin(void* userdata)
{ {
//return LocalMP::Begin(); int inst = ((EmuInstance*)userdata)->getInstanceID();
LocalMP::Begin(inst);
} }
void MP_End(void* userdata) void MP_End(void* userdata)
{ {
//return LocalMP::End(); int inst = ((EmuInstance*)userdata)->getInstanceID();
LocalMP::End(inst);
} }
int MP_SendPacket(u8* data, int len, u64 timestamp, void* userdata) int MP_SendPacket(u8* data, int len, u64 timestamp, void* userdata)
{ {
//return LocalMP::SendPacket(data, len, timestamp); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::SendPacket(inst, data, len, timestamp);
} }
int MP_RecvPacket(u8* data, u64* timestamp, void* userdata) int MP_RecvPacket(u8* data, u64* timestamp, void* userdata)
{ {
//return LocalMP::RecvPacket(data, timestamp); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::RecvPacket(inst, data, timestamp);
} }
int MP_SendCmd(u8* data, int len, u64 timestamp, void* userdata) int MP_SendCmd(u8* data, int len, u64 timestamp, void* userdata)
{ {
//return LocalMP::SendCmd(data, len, timestamp); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::SendCmd(inst, data, len, timestamp);
} }
int MP_SendReply(u8* data, int len, u64 timestamp, u16 aid, void* userdata) int MP_SendReply(u8* data, int len, u64 timestamp, u16 aid, void* userdata)
{ {
//return LocalMP::SendReply(data, len, timestamp, aid); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::SendReply(inst, data, len, timestamp, aid);
} }
int MP_SendAck(u8* data, int len, u64 timestamp, void* userdata) int MP_SendAck(u8* data, int len, u64 timestamp, void* userdata)
{ {
//return LocalMP::SendAck(data, len, timestamp); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::SendAck(inst, data, len, timestamp);
} }
int MP_RecvHostPacket(u8* data, u64* timestamp, void* userdata) int MP_RecvHostPacket(u8* data, u64* timestamp, void* userdata)
{ {
//return LocalMP::RecvHostPacket(data, timestamp); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::RecvHostPacket(inst, data, timestamp);
} }
u16 MP_RecvReplies(u8* data, u64 timestamp, u16 aidmask, void* userdata) u16 MP_RecvReplies(u8* data, u64 timestamp, u16 aidmask, void* userdata)
{ {
//return LocalMP::RecvReplies(data, timestamp, aidmask); int inst = ((EmuInstance*)userdata)->getInstanceID();
return 0; return LocalMP::RecvReplies(inst, data, timestamp, aidmask);
} }
bool LAN_Init(void* userdata) bool LAN_Init(void* userdata)

View File

@ -74,6 +74,7 @@
#include "EmuInstance.h" #include "EmuInstance.h"
#include "ArchiveUtil.h" #include "ArchiveUtil.h"
#include "CameraManager.h" #include "CameraManager.h"
#include "LocalMP.h"
#include "CLI.h" #include "CLI.h"
@ -266,6 +267,8 @@ int main(int argc, char** argv)
} }
} }
LocalMP::Init();
/* mainWindow = new MainWindow(); /* mainWindow = new MainWindow();
if (options->fullscreen) if (options->fullscreen)
ToggleFullscreen(mainWindow); ToggleFullscreen(mainWindow);
@ -318,6 +321,8 @@ int main(int argc, char** argv)
// but with this we make extra sure they are all deleted // but with this we make extra sure they are all deleted
deleteAllEmuInstances(); deleteAllEmuInstances();
LocalMP::DeInit();
//AudioInOut::DeInit(); //AudioInOut::DeInit();
delete camManager[0]; delete camManager[0];
delete camManager[1]; delete camManager[1];