lay base for supporting different MP interfaces

This commit is contained in:
Arisotura 2024-08-07 13:19:46 +02:00
parent 0ad1fa8514
commit bdbcd9c351
9 changed files with 109 additions and 42 deletions

View File

@ -39,7 +39,7 @@
#include "Config.h" #include "Config.h"
#include "Platform.h" #include "Platform.h"
#include "Net.h" #include "Net.h"
#include "LocalMP.h" #include "MPInterface.h"
#include "NDS.h" #include "NDS.h"
#include "DSi.h" #include "DSi.h"
@ -62,7 +62,6 @@ using namespace melonDS::Platform;
MainWindow* topWindow = nullptr; MainWindow* topWindow = nullptr;
const string kWifiSettingsPath = "wfcsettings.bin"; const string kWifiSettingsPath = "wfcsettings.bin";
extern LocalMP localMp;
extern Net net; extern Net net;
@ -121,7 +120,7 @@ EmuInstance::~EmuInstance()
deleting = true; deleting = true;
deleteAllWindows(); deleteAllWindows();
localMp.End(instanceID); MPInterface::Get().End(instanceID);
emuThread->emuExit(); emuThread->emuExit();
emuThread->wait(); emuThread->wait();

View File

@ -38,7 +38,7 @@
#include "main.h" #include "main.h"
#include "CameraManager.h" #include "CameraManager.h"
#include "Net.h" #include "Net.h"
#include "LocalMP.h" #include "MPInterface.h"
#include "SPI_Firmware.h" #include "SPI_Firmware.h"
#ifdef __WIN32__ #ifdef __WIN32__
@ -47,7 +47,7 @@
#endif // __WIN32__ #endif // __WIN32__
extern CameraManager* camManager[2]; extern CameraManager* camManager[2];
extern melonDS::LocalMP localMp;
extern melonDS::Net net; extern melonDS::Net net;
namespace melonDS::Platform namespace melonDS::Platform
@ -458,55 +458,55 @@ void WriteDateTime(int year, int month, int day, int hour, int minute, int secon
void MP_Begin(void* userdata) void MP_Begin(void* userdata)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
localMp.Begin(inst); MPInterface::Get().Begin(inst);
} }
void MP_End(void* userdata) void MP_End(void* userdata)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
localMp.End(inst); MPInterface::Get().End(inst);
} }
int MP_SendPacket(u8* data, int len, u64 timestamp, void* userdata) int MP_SendPacket(u8* data, int len, u64 timestamp, void* userdata)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.SendPacket(inst, data, len, timestamp); return MPInterface::Get().SendPacket(inst, data, len, timestamp);
} }
int MP_RecvPacket(u8* data, u64* timestamp, void* userdata) int MP_RecvPacket(u8* data, u64* timestamp, void* userdata)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.RecvPacket(inst, data, timestamp); return MPInterface::Get().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)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.SendCmd(inst, data, len, timestamp); return MPInterface::Get().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)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.SendReply(inst, data, len, timestamp, aid); return MPInterface::Get().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)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.SendAck(inst, data, len, timestamp); return MPInterface::Get().SendAck(inst, data, len, timestamp);
} }
int MP_RecvHostPacket(u8* data, u64* timestamp, void* userdata) int MP_RecvHostPacket(u8* data, u64* timestamp, void* userdata)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.RecvHostPacket(inst, data, timestamp); return MPInterface::Get().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)
{ {
int inst = ((EmuInstance*)userdata)->getInstanceID(); int inst = ((EmuInstance*)userdata)->getInstanceID();
return localMp.RecvReplies(inst, data, timestamp, aidmask); return MPInterface::Get().RecvReplies(inst, data, timestamp, aidmask);
} }

View File

@ -72,7 +72,7 @@
#include "Config.h" #include "Config.h"
#include "version.h" #include "version.h"
#include "Savestate.h" #include "Savestate.h"
#include "LocalMP.h" #include "MPInterface.h"
#include "LANDialog.h" #include "LANDialog.h"
//#include "main_shaders.h" //#include "main_shaders.h"
@ -88,7 +88,6 @@ using namespace melonDS;
extern CameraManager* camManager[2]; extern CameraManager* camManager[2];
extern bool camStarted[2]; extern bool camStarted[2];
extern LocalMP localMp;
QString NdsRomMimeType = "application/x-nintendo-ds-rom"; QString NdsRomMimeType = "application/x-nintendo-ds-rom";
@ -1886,7 +1885,7 @@ void MainWindow::onMPSettingsFinished(int res)
{ {
emuInstance->mpAudioMode = globalCfg.GetInt("MP.AudioMode"); emuInstance->mpAudioMode = globalCfg.GetInt("MP.AudioMode");
emuInstance->audioMute(); emuInstance->audioMute();
localMp.SetRecvTimeout(globalCfg.GetInt("MP.RecvTimeout")); MPInterface::Get().SetRecvTimeout(globalCfg.GetInt("MP.RecvTimeout"));
emuThread->emuUnpause(); emuThread->emuUnpause();
} }

View File

@ -22,18 +22,14 @@
#include <string.h> #include <string.h>
#include <optional> #include <optional>
#include <vector>
#include <string> #include <string>
#include <algorithm>
#include <QProcess>
#include <QApplication> #include <QApplication>
#include <QStyle>
#include <QMessageBox> #include <QMessageBox>
#include <QMenuBar> #include <QMenuBar>
#include <QMimeDatabase>
#include <QFileDialog> #include <QFileDialog>
#include <QInputDialog> #include <QInputDialog>
#include <QPaintEvent>
#include <QPainter> #include <QPainter>
#include <QKeyEvent> #include <QKeyEvent>
#include <QMimeData> #include <QMimeData>
@ -57,24 +53,14 @@
#include "duckstation/gl/context.h" #include "duckstation/gl/context.h"
#include "main.h" #include "main.h"
#include "CheatsDialog.h"
#include "DateTimeDialog.h"
#include "EmuSettingsDialog.h"
#include "InputConfig/InputConfigDialog.h"
#include "VideoSettingsDialog.h"
#include "ROMInfoDialog.h"
#include "RAMInfoDialog.h"
#include "PowerManagement/PowerManagementDialog.h"
#include "version.h" #include "version.h"
#include "Config.h" #include "Config.h"
#include "DSi.h"
#include "EmuInstance.h" #include "EmuInstance.h"
#include "ArchiveUtil.h" #include "ArchiveUtil.h"
#include "CameraManager.h" #include "CameraManager.h"
#include "LocalMP.h" #include "MPInterface.h"
#include "Net.h" #include "Net.h"
#include "CLI.h" #include "CLI.h"
@ -95,10 +81,11 @@ EmuInstance* emuInstances[kMaxEmuInstances];
CameraManager* camManager[2]; CameraManager* camManager[2];
bool camStarted[2]; bool camStarted[2];
LocalMP localMp;
std::optional<LibPCap> pcap; std::optional<LibPCap> pcap;
Net net; Net net;
void NetInit() void NetInit()
{ {
Config::Table cfg = Config::GetGlobalTable(); Config::Table cfg = Config::GetGlobalTable();
@ -321,7 +308,11 @@ int main(int argc, char** argv)
} }
} }
// localMp is initialized at this point // default MP interface type is local MP
// this will be changed if a LAN or netplay session is initiated
MPInterface::Set(MPInterface_Local);
MPInterface::Get().SetRecvTimeout(Config::GetGlobalTable().GetInt("MP.RecvTimeout"));
NetInit(); NetInit();
createEmuInstance(); createEmuInstance();

View File

@ -5,6 +5,7 @@ add_library(net-utils STATIC
PacketDispatcher.cpp PacketDispatcher.cpp
LocalMP.cpp LocalMP.cpp
MPInterface.h MPInterface.h
MPInterface.cpp
) )
target_include_directories(net-utils PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") target_include_directories(net-utils PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")

View File

@ -19,8 +19,6 @@
#include <cstring> #include <cstring>
#include "LocalMP.h" #include "LocalMP.h"
#include "Platform.h"
#include "types.h"
using namespace melonDS; using namespace melonDS;
using namespace melonDS::Platform; using namespace melonDS::Platform;

View File

@ -21,6 +21,7 @@
#include "types.h" #include "types.h"
#include "Platform.h" #include "Platform.h"
#include "MPInterface.h"
namespace melonDS namespace melonDS
{ {
@ -46,7 +47,7 @@ constexpr u32 kPacketQueueSize = 0x10000;
constexpr u32 kReplyQueueSize = 0x10000; constexpr u32 kReplyQueueSize = 0x10000;
constexpr u32 kMaxFrameSize = 0x948; constexpr u32 kMaxFrameSize = 0x948;
class LocalMP class LocalMP : public MPInterface
{ {
public: public:
LocalMP() noexcept; LocalMP() noexcept;
@ -56,8 +57,7 @@ public:
LocalMP& operator=(LocalMP&& other) = delete; LocalMP& operator=(LocalMP&& other) = delete;
~LocalMP() noexcept; ~LocalMP() noexcept;
[[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; } void Process() {}
void SetRecvTimeout(int timeout) noexcept { RecvTimeout = timeout; }
void Begin(int inst); void Begin(int inst);
void End(int inst); void End(int inst);
@ -69,11 +69,13 @@ public:
int SendAck(int inst, u8* data, int len, u64 timestamp); int SendAck(int inst, u8* data, int len, u64 timestamp);
int RecvHostPacket(int inst, u8* data, u64* timestamp); int RecvHostPacket(int inst, u8* data, u64* timestamp);
u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask); u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask);
private: private:
void FIFORead(int inst, int fifo, void* buf, int len) noexcept; void FIFORead(int inst, int fifo, void* buf, int len) noexcept;
void FIFOWrite(int inst, int fifo, void* buf, int len) noexcept; void FIFOWrite(int inst, int fifo, void* buf, int len) noexcept;
int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp) noexcept; int SendPacketGeneric(int inst, u32 type, u8* packet, int len, u64 timestamp) noexcept;
int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp) noexcept; int RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp) noexcept;
Platform::Mutex* MPQueueLock; Platform::Mutex* MPQueueLock;
MPStatusData MPStatus {}; MPStatusData MPStatus {};
u8 MPPacketQueue[kPacketQueueSize] {}; u8 MPPacketQueue[kPacketQueueSize] {};
@ -81,8 +83,6 @@ private:
u32 PacketReadOffset[16] {}; u32 PacketReadOffset[16] {};
u32 ReplyReadOffset[16] {}; u32 ReplyReadOffset[16] {};
int RecvTimeout = 25;
int LastHostID = -1; int LastHostID = -1;
Platform::Semaphore* SemPool[32] {}; Platform::Semaphore* SemPool[32] {};
}; };

60
src/net/MPInterface.cpp Normal file
View File

@ -0,0 +1,60 @@
/*
Copyright 2016-2024 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#include "MPInterface.h"
#include "LocalMP.h"
namespace melonDS
{
class DummyMP : public MPInterface
{
public:
void Process() override {}
void Begin(int inst) override {}
void End(int inst) override {}
int SendPacket(int inst, u8* data, int len, u64 timestamp) override { return 0; }
int RecvPacket(int inst, u8* data, u64* timestamp) override { return 0; }
int SendCmd(int inst, u8* data, int len, u64 timestamp) override { return 0; }
int SendReply(int inst, u8* data, int len, u64 timestamp, u16 aid) override { return 0; }
int SendAck(int inst, u8* data, int len, u64 timestamp) override { return 0; }
int RecvHostPacket(int inst, u8* data, u64* timestamp) override { return 0; }
u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask) override { return 0; }
};
std::unique_ptr<MPInterface> MPInterface::Current(std::make_unique<DummyMP>());
void MPInterface::Set(MPInterfaceType type)
{
switch (type)
{
case MPInterface_Local:
Current = std::make_unique<LocalMP>();
break;
default:
Current = std::make_unique<DummyMP>();
break;
}
}
}

View File

@ -19,17 +19,33 @@
#ifndef MPINTERFACE_H #ifndef MPINTERFACE_H
#define MPINTERFACE_H #define MPINTERFACE_H
#include <memory>
#include "types.h" #include "types.h"
namespace melonDS namespace melonDS
{ {
// TODO: provision for excluding unwanted interfaces at compile time
enum MPInterfaceType
{
MPInterface_Dummy = -1,
MPInterface_Local,
MPInterface_LAN,
MPInterface_Netplay,
};
class MPInterface class MPInterface
{ {
public: public:
static MPInterface& Get() { return *Current; }
static void Set(MPInterfaceType type);
[[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; } [[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; }
void SetRecvTimeout(int timeout) noexcept { RecvTimeout = timeout; } void SetRecvTimeout(int timeout) noexcept { RecvTimeout = timeout; }
// function called every video frame
virtual void Process() = 0;
virtual void Begin(int inst) = 0; virtual void Begin(int inst) = 0;
virtual void End(int inst) = 0; virtual void End(int inst) = 0;
@ -43,6 +59,9 @@ public:
protected: protected:
int RecvTimeout = 25; int RecvTimeout = 25;
private:
static std::unique_ptr<MPInterface> Current;
}; };
} }