From bdbcd9c351dea7a04900a285f102ae57da60f865 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 7 Aug 2024 13:19:46 +0200 Subject: [PATCH] lay base for supporting different MP interfaces --- src/frontend/qt_sdl/EmuInstance.cpp | 5 +-- src/frontend/qt_sdl/Platform.cpp | 22 +++++------ src/frontend/qt_sdl/Window.cpp | 5 +-- src/frontend/qt_sdl/main.cpp | 27 +++++-------- src/net/CMakeLists.txt | 1 + src/net/LocalMP.cpp | 2 - src/net/LocalMP.h | 10 ++--- src/net/MPInterface.cpp | 60 +++++++++++++++++++++++++++++ src/net/MPInterface.h | 19 +++++++++ 9 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 src/net/MPInterface.cpp diff --git a/src/frontend/qt_sdl/EmuInstance.cpp b/src/frontend/qt_sdl/EmuInstance.cpp index 27d804ac..b29d2b09 100644 --- a/src/frontend/qt_sdl/EmuInstance.cpp +++ b/src/frontend/qt_sdl/EmuInstance.cpp @@ -39,7 +39,7 @@ #include "Config.h" #include "Platform.h" #include "Net.h" -#include "LocalMP.h" +#include "MPInterface.h" #include "NDS.h" #include "DSi.h" @@ -62,7 +62,6 @@ using namespace melonDS::Platform; MainWindow* topWindow = nullptr; const string kWifiSettingsPath = "wfcsettings.bin"; -extern LocalMP localMp; extern Net net; @@ -121,7 +120,7 @@ EmuInstance::~EmuInstance() deleting = true; deleteAllWindows(); - localMp.End(instanceID); + MPInterface::Get().End(instanceID); emuThread->emuExit(); emuThread->wait(); diff --git a/src/frontend/qt_sdl/Platform.cpp b/src/frontend/qt_sdl/Platform.cpp index 217f1b45..920684e7 100644 --- a/src/frontend/qt_sdl/Platform.cpp +++ b/src/frontend/qt_sdl/Platform.cpp @@ -38,7 +38,7 @@ #include "main.h" #include "CameraManager.h" #include "Net.h" -#include "LocalMP.h" +#include "MPInterface.h" #include "SPI_Firmware.h" #ifdef __WIN32__ @@ -47,7 +47,7 @@ #endif // __WIN32__ extern CameraManager* camManager[2]; -extern melonDS::LocalMP localMp; + extern melonDS::Net net; 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) { int inst = ((EmuInstance*)userdata)->getInstanceID(); - localMp.Begin(inst); + MPInterface::Get().Begin(inst); } void MP_End(void* userdata) { int inst = ((EmuInstance*)userdata)->getInstanceID(); - localMp.End(inst); + MPInterface::Get().End(inst); } int MP_SendPacket(u8* data, int len, u64 timestamp, void* userdata) { 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 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 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 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 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 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) { int inst = ((EmuInstance*)userdata)->getInstanceID(); - return localMp.RecvReplies(inst, data, timestamp, aidmask); + return MPInterface::Get().RecvReplies(inst, data, timestamp, aidmask); } diff --git a/src/frontend/qt_sdl/Window.cpp b/src/frontend/qt_sdl/Window.cpp index e2a6fa03..84cc7222 100644 --- a/src/frontend/qt_sdl/Window.cpp +++ b/src/frontend/qt_sdl/Window.cpp @@ -72,7 +72,7 @@ #include "Config.h" #include "version.h" #include "Savestate.h" -#include "LocalMP.h" +#include "MPInterface.h" #include "LANDialog.h" //#include "main_shaders.h" @@ -88,7 +88,6 @@ using namespace melonDS; extern CameraManager* camManager[2]; extern bool camStarted[2]; -extern LocalMP localMp; QString NdsRomMimeType = "application/x-nintendo-ds-rom"; @@ -1886,7 +1885,7 @@ void MainWindow::onMPSettingsFinished(int res) { emuInstance->mpAudioMode = globalCfg.GetInt("MP.AudioMode"); emuInstance->audioMute(); - localMp.SetRecvTimeout(globalCfg.GetInt("MP.RecvTimeout")); + MPInterface::Get().SetRecvTimeout(globalCfg.GetInt("MP.RecvTimeout")); emuThread->emuUnpause(); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 17959c5e..06543af2 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -22,18 +22,14 @@ #include #include -#include #include -#include -#include #include +#include #include #include -#include #include #include -#include #include #include #include @@ -57,24 +53,14 @@ #include "duckstation/gl/context.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 "Config.h" -#include "DSi.h" #include "EmuInstance.h" #include "ArchiveUtil.h" #include "CameraManager.h" -#include "LocalMP.h" +#include "MPInterface.h" #include "Net.h" #include "CLI.h" @@ -95,10 +81,11 @@ EmuInstance* emuInstances[kMaxEmuInstances]; CameraManager* camManager[2]; bool camStarted[2]; -LocalMP localMp; + std::optional pcap; Net net; + void NetInit() { 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(); createEmuInstance(); diff --git a/src/net/CMakeLists.txt b/src/net/CMakeLists.txt index 0b0be117..28cedfd8 100644 --- a/src/net/CMakeLists.txt +++ b/src/net/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(net-utils STATIC PacketDispatcher.cpp LocalMP.cpp MPInterface.h + MPInterface.cpp ) target_include_directories(net-utils PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}") diff --git a/src/net/LocalMP.cpp b/src/net/LocalMP.cpp index 0f6889ac..a789964e 100644 --- a/src/net/LocalMP.cpp +++ b/src/net/LocalMP.cpp @@ -19,8 +19,6 @@ #include #include "LocalMP.h" -#include "Platform.h" -#include "types.h" using namespace melonDS; using namespace melonDS::Platform; diff --git a/src/net/LocalMP.h b/src/net/LocalMP.h index 4de6f30f..ced1b842 100644 --- a/src/net/LocalMP.h +++ b/src/net/LocalMP.h @@ -21,6 +21,7 @@ #include "types.h" #include "Platform.h" +#include "MPInterface.h" namespace melonDS { @@ -46,7 +47,7 @@ constexpr u32 kPacketQueueSize = 0x10000; constexpr u32 kReplyQueueSize = 0x10000; constexpr u32 kMaxFrameSize = 0x948; -class LocalMP +class LocalMP : public MPInterface { public: LocalMP() noexcept; @@ -56,8 +57,7 @@ public: LocalMP& operator=(LocalMP&& other) = delete; ~LocalMP() noexcept; - [[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; } - void SetRecvTimeout(int timeout) noexcept { RecvTimeout = timeout; } + void Process() {} void Begin(int inst); void End(int inst); @@ -69,11 +69,13 @@ public: int SendAck(int inst, u8* data, int len, u64 timestamp); int RecvHostPacket(int inst, u8* data, u64* timestamp); u16 RecvReplies(int inst, u8* data, u64 timestamp, u16 aidmask); + private: void FIFORead(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 RecvPacketGeneric(int inst, u8* packet, bool block, u64* timestamp) noexcept; + Platform::Mutex* MPQueueLock; MPStatusData MPStatus {}; u8 MPPacketQueue[kPacketQueueSize] {}; @@ -81,8 +83,6 @@ private: u32 PacketReadOffset[16] {}; u32 ReplyReadOffset[16] {}; - int RecvTimeout = 25; - int LastHostID = -1; Platform::Semaphore* SemPool[32] {}; }; diff --git a/src/net/MPInterface.cpp b/src/net/MPInterface.cpp new file mode 100644 index 00000000..1bf3539c --- /dev/null +++ b/src/net/MPInterface.cpp @@ -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::Current(std::make_unique()); + + +void MPInterface::Set(MPInterfaceType type) +{ + switch (type) + { + case MPInterface_Local: + Current = std::make_unique(); + break; + + default: + Current = std::make_unique(); + break; + } +} + +} diff --git a/src/net/MPInterface.h b/src/net/MPInterface.h index e86736e6..27622bd7 100644 --- a/src/net/MPInterface.h +++ b/src/net/MPInterface.h @@ -19,17 +19,33 @@ #ifndef MPINTERFACE_H #define MPINTERFACE_H +#include #include "types.h" namespace melonDS { +// TODO: provision for excluding unwanted interfaces at compile time +enum MPInterfaceType +{ + MPInterface_Dummy = -1, + MPInterface_Local, + MPInterface_LAN, + MPInterface_Netplay, +}; + class MPInterface { public: + static MPInterface& Get() { return *Current; } + static void Set(MPInterfaceType type); + [[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; } void SetRecvTimeout(int timeout) noexcept { RecvTimeout = timeout; } + // function called every video frame + virtual void Process() = 0; + virtual void Begin(int inst) = 0; virtual void End(int inst) = 0; @@ -43,6 +59,9 @@ public: protected: int RecvTimeout = 25; + +private: + static std::unique_ptr Current; }; }