mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-12-16 04:09:39 +00:00
Merge bf79b641a1 into ed2fe134aa
This commit is contained in:
commit
e5b9f67a5f
8
.gitmodules
vendored
8
.gitmodules
vendored
@ -14,6 +14,10 @@
|
||||
path = Externals/libusb/libusb
|
||||
url = https://github.com/libusb/libusb.git
|
||||
shallow = true
|
||||
[submodule "Externals/libzmq/libzmq"]
|
||||
path = Externals/libzmq/libzmq
|
||||
url = https://github.com/zeromq/libzmq.git
|
||||
shallow = true
|
||||
[submodule "Externals/spirv_cross/SPIRV-Cross"]
|
||||
path = Externals/spirv_cross/SPIRV-Cross
|
||||
url = https://github.com/KhronosGroup/SPIRV-Cross.git
|
||||
@ -34,6 +38,10 @@
|
||||
path = Externals/VulkanMemoryAllocator
|
||||
url = https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
|
||||
shallow = true
|
||||
[submodule "Externals/Cross-Compatible-FileLock-Windows-and-Linux"]
|
||||
path = Externals/Cross-Compatible-FileLock-Windows-and-Linux
|
||||
url = https://github.com/KaganCanSit/Cross-Compatible-FileLock-Windows-and-Linux.git
|
||||
shallow = true
|
||||
[submodule "Externals/cubeb/cubeb"]
|
||||
path = Externals/cubeb/cubeb
|
||||
url = https://github.com/mozilla/cubeb.git
|
||||
|
||||
@ -786,8 +786,10 @@ endif()
|
||||
|
||||
add_subdirectory(Externals/watcher)
|
||||
|
||||
if(WIN32 OR LINUX)
|
||||
if(NOT ANDROID AND NOT APPLE)
|
||||
add_subdirectory(Externals/cpp-ipc)
|
||||
elseif(APPLE)
|
||||
add_subdirectory(Externals/libzmq)
|
||||
endif()
|
||||
|
||||
########################################
|
||||
|
||||
1
Externals/Cross-Compatible-FileLock-Windows-and-Linux
vendored
Submodule
1
Externals/Cross-Compatible-FileLock-Windows-and-Linux
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 42ffdc24b06a85383e1b7a20e09931d7849533e7
|
||||
2
Externals/cpp-ipc/cpp-ipc
vendored
2
Externals/cpp-ipc/cpp-ipc
vendored
@ -1 +1 @@
|
||||
Subproject commit a0c7725a1441d18bc768d748a93e512a0fa7ab52
|
||||
Subproject commit ce0773b3e6d5abaa8d104100c5704321113853ca
|
||||
17
Externals/libzmq/CMakeLists.txt
vendored
Normal file
17
Externals/libzmq/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
set(ENABLE_DRAFTS OFF)
|
||||
set(BUILD_TESTS OFF)
|
||||
set(WITH_DOCS OFF)
|
||||
set(BUILD_SHARED OFF)
|
||||
set(BUILD_STATIC ON)
|
||||
|
||||
add_subdirectory(libzmq)
|
||||
|
||||
dolphin_disable_warnings(objects)
|
||||
dolphin_disable_warnings(libzmq-static)
|
||||
|
||||
if (NOT MSVC)
|
||||
target_compile_options(objects PRIVATE "-fexceptions")
|
||||
target_compile_options(libzmq-static PRIVATE "-fexceptions")
|
||||
endif ()
|
||||
|
||||
add_library(libzmq::libzmq ALIAS libzmq-static)
|
||||
1
Externals/libzmq/libzmq
vendored
Submodule
1
Externals/libzmq/libzmq
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 7a7bfa10e6b0e99210ed9397369b59f9e69cef8e
|
||||
4
Externals/licenses.md
vendored
4
Externals/licenses.md
vendored
@ -10,6 +10,8 @@ Dolphin includes or links code of the following third-party software projects:
|
||||
[bzip2 license](https://www.sourceware.org/git/?p=bzip2.git;a=blob;f=LICENSE;hb=HEAD) (similar to 3-clause BSD)
|
||||
- [cpp-ipc](https://github.com/mutouyun/cpp-ipc):
|
||||
[MIT](https://github.com/mutouyun/cpp-ipc/blob/master/LICENSE)
|
||||
- [Cross-Compatible-FileLock-Windows-and-Linux](https://github.com/KaganCanSit/Cross-Compatible-FileLock-Windows-and-Linux):
|
||||
[MIT](https://github.com/KaganCanSit/Cross-Compatible-FileLock-Windows-and-Linux/blob/main/LICENSE)
|
||||
- [cubeb](https://github.com/kinetiknz/cubeb):
|
||||
[ISC](https://github.com/kinetiknz/cubeb/blob/master/LICENSE)
|
||||
- [Discord-RPC](https://github.com/discordapp/discord-rpc):
|
||||
@ -44,6 +46,8 @@ Dolphin includes or links code of the following third-party software projects:
|
||||
[University of Illinois/NCSA Open Source license](http://llvm.org/docs/DeveloperPolicy.html#license)
|
||||
- [LZO](http://www.oberhumer.com/opensource/lzo/):
|
||||
[GPLv2+](http://www.oberhumer.com/opensource/gpl.html)
|
||||
- [libzmq](https://github.com/zeromq/libzmq):
|
||||
[MPL 2.0](https://github.com/zeromq/libzmq/blob/master/LICENSE)
|
||||
- [mGBA](http://mgba.io)
|
||||
[MPL 2.0](https://github.com/mgba-emu/mgba/blob/master/LICENSE)
|
||||
- [MiniUPnPc](http://miniupnp.free.fr/):
|
||||
|
||||
@ -801,9 +801,13 @@ if(UNIX)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(WIN32 OR LINUX)
|
||||
if(NOT ANDROID AND NOT APPLE)
|
||||
target_sources(core PRIVATE HW/EXI/BBA/IPC.cpp)
|
||||
target_link_libraries(core PRIVATE cpp-ipc::ipc)
|
||||
elseif(APPLE)
|
||||
target_sources(core PRIVATE HW/EXI/BBA/IPC_zmq.cpp)
|
||||
target_link_libraries(core PRIVATE libzmq::libzmq)
|
||||
target_include_directories(core PRIVATE "${CMAKE_SOURCE_DIR}/Externals/Cross-Compatible-FileLock-Windows-and-Linux/include")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
|
||||
209
Source/Core/Core/HW/EXI/BBA/IPC_zmq.cpp
Normal file
209
Source/Core/Core/HW/EXI/BBA/IPC_zmq.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
// Copyright 2008 Dolphin Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <bit>
|
||||
#include <chrono>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <mutex>
|
||||
|
||||
#include <FileLockFactory.hpp>
|
||||
#include <zmq.h>
|
||||
|
||||
#include "Core/HW/EXI/EXI_DeviceEthernet.h"
|
||||
|
||||
namespace ExpansionInterface
|
||||
{
|
||||
|
||||
CEXIETHERNET::IPCBBAInterface::IPCBBAInterface(CEXIETHERNET* const eth_ref)
|
||||
: CEXIETHERNET::NetworkInterface(eth_ref), m_context(zmq_ctx_new()),
|
||||
m_proxy_thread(&CEXIETHERNET::IPCBBAInterface::ProxyThreadHandler, this)
|
||||
{
|
||||
}
|
||||
|
||||
CEXIETHERNET::IPCBBAInterface::~IPCBBAInterface()
|
||||
{
|
||||
m_proxy_thread_shutdown.Set();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{m_proxy_mutex};
|
||||
|
||||
if (m_proxy_publisher)
|
||||
{
|
||||
zmq_close(m_proxy_publisher);
|
||||
m_proxy_publisher = nullptr;
|
||||
}
|
||||
if (m_proxy_subscriber)
|
||||
{
|
||||
zmq_close(m_proxy_subscriber);
|
||||
m_proxy_subscriber = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
zmq_ctx_term(m_context);
|
||||
m_context = nullptr;
|
||||
|
||||
if (m_proxy_thread.joinable())
|
||||
{
|
||||
m_proxy_thread.join();
|
||||
}
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::IPCBBAInterface::Activate()
|
||||
{
|
||||
if (m_active)
|
||||
return false;
|
||||
|
||||
const u32 linger{0};
|
||||
|
||||
m_publisher = zmq_socket(m_context, ZMQ_PUB);
|
||||
zmq_setsockopt(m_publisher, ZMQ_LINGER, &linger, sizeof(linger));
|
||||
zmq_connect(m_publisher, "ipc:///tmp/dolphin-bba-outbox");
|
||||
|
||||
m_subscriber = zmq_socket(m_context, ZMQ_SUB);
|
||||
zmq_setsockopt(m_subscriber, ZMQ_LINGER, &linger, sizeof(linger));
|
||||
zmq_setsockopt(m_subscriber, ZMQ_SUBSCRIBE, "", 0);
|
||||
zmq_connect(m_subscriber, "ipc:///tmp/dolphin-bba-inbox");
|
||||
|
||||
m_read_enabled.Clear();
|
||||
m_read_thread_shutdown.Clear();
|
||||
|
||||
m_active = true;
|
||||
|
||||
return RecvInit();
|
||||
}
|
||||
|
||||
void CEXIETHERNET::IPCBBAInterface::Deactivate()
|
||||
{
|
||||
if (!m_active)
|
||||
return;
|
||||
|
||||
m_read_enabled.Clear();
|
||||
m_read_thread_shutdown.Set();
|
||||
|
||||
if (m_read_thread.joinable())
|
||||
{
|
||||
m_read_thread.join();
|
||||
}
|
||||
|
||||
zmq_close(m_publisher);
|
||||
zmq_close(m_subscriber);
|
||||
m_publisher = nullptr;
|
||||
m_subscriber = nullptr;
|
||||
|
||||
m_active = false;
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::IPCBBAInterface::IsActivated()
|
||||
{
|
||||
return m_active;
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::IPCBBAInterface::SendFrame(const u8* const frame, const u32 size)
|
||||
{
|
||||
if (!m_active)
|
||||
return false;
|
||||
|
||||
std::vector<u8> message;
|
||||
const u64 self{std::bit_cast<u64>(this)};
|
||||
message.resize(sizeof(self) + static_cast<u64>(size));
|
||||
std::memcpy(message.data(), &self, sizeof(self));
|
||||
std::memcpy(message.data() + sizeof(self), frame, static_cast<u64>(size));
|
||||
|
||||
zmq_send(m_publisher, message.data(), message.size(), 0);
|
||||
m_eth_ref->SendComplete();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CEXIETHERNET::IPCBBAInterface::RecvInit()
|
||||
{
|
||||
m_read_thread = std::thread(&CEXIETHERNET::IPCBBAInterface::ReadThreadHandler, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CEXIETHERNET::IPCBBAInterface::RecvStart()
|
||||
{
|
||||
m_read_enabled.Set();
|
||||
}
|
||||
|
||||
void CEXIETHERNET::IPCBBAInterface::RecvStop()
|
||||
{
|
||||
m_read_enabled.Clear();
|
||||
}
|
||||
|
||||
void CEXIETHERNET::IPCBBAInterface::ReadThreadHandler()
|
||||
{
|
||||
const u64 self{std::bit_cast<u64>(this)};
|
||||
|
||||
std::vector<u8> buffer;
|
||||
buffer.resize(sizeof(self) + BBA_RECV_SIZE);
|
||||
|
||||
while (!m_read_thread_shutdown.IsSet())
|
||||
{
|
||||
zmq_pollitem_t pollitem{};
|
||||
pollitem.socket = m_subscriber;
|
||||
pollitem.events = ZMQ_POLLIN;
|
||||
|
||||
const int event_count{zmq_poll(&pollitem, 1, 50)};
|
||||
for (int i{0}; i < event_count; ++i)
|
||||
{
|
||||
const int read{zmq_recv(m_subscriber, buffer.data(), buffer.size(), 0)};
|
||||
if (read < static_cast<int>(sizeof(self)))
|
||||
continue;
|
||||
|
||||
u64 id{};
|
||||
std::memcpy(&id, buffer.data(), sizeof(self));
|
||||
|
||||
const bool self_message{id == self};
|
||||
if (self_message)
|
||||
continue;
|
||||
|
||||
if (!m_read_enabled.IsSet())
|
||||
continue;
|
||||
|
||||
const u8* const frame{buffer.data() + sizeof(self)};
|
||||
const u64 size{read - sizeof(self)};
|
||||
|
||||
std::memcpy(m_eth_ref->mRecvBuffer.get(), frame, size);
|
||||
m_eth_ref->mRecvBufferLength = static_cast<u32>(size);
|
||||
m_eth_ref->RecvHandlePacket();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CEXIETHERNET::IPCBBAInterface::ProxyThreadHandler()
|
||||
{
|
||||
while (!m_proxy_thread_shutdown.IsSet())
|
||||
{
|
||||
// The first instance that acquires the filelock becomes the proxy.
|
||||
const auto filelock = file_lock::FileLockFactory::CreateTimedLockContext(
|
||||
"/tmp/dolphin-bba-filelock", std::chrono::seconds(1));
|
||||
if (!filelock)
|
||||
continue;
|
||||
|
||||
void* proxy_subscriber;
|
||||
void* proxy_publisher;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock{m_proxy_mutex};
|
||||
|
||||
const u32 linger{0};
|
||||
|
||||
m_proxy_subscriber = zmq_socket(m_context, ZMQ_XSUB);
|
||||
zmq_setsockopt(m_proxy_subscriber, ZMQ_LINGER, &linger, sizeof(linger));
|
||||
zmq_setsockopt(m_proxy_subscriber, ZMQ_SUBSCRIBE, "", 0);
|
||||
zmq_bind(m_proxy_subscriber, "ipc:///tmp/dolphin-bba-outbox");
|
||||
|
||||
m_proxy_publisher = zmq_socket(m_context, ZMQ_XPUB);
|
||||
zmq_setsockopt(m_proxy_publisher, ZMQ_LINGER, &linger, sizeof(linger));
|
||||
zmq_bind(m_proxy_publisher, "ipc:///tmp/dolphin-bba-inbox");
|
||||
|
||||
proxy_subscriber = m_proxy_subscriber;
|
||||
proxy_publisher = m_proxy_publisher;
|
||||
}
|
||||
|
||||
zmq_proxy(proxy_subscriber, proxy_publisher, nullptr);
|
||||
}
|
||||
}
|
||||
} // namespace ExpansionInterface
|
||||
@ -15,7 +15,7 @@
|
||||
#endif
|
||||
|
||||
#include <SFML/Network.hpp>
|
||||
#if defined(WIN32) || (defined(__linux__) && !defined(__ANDROID__))
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
#include <libipc/ipc.h>
|
||||
#endif
|
||||
|
||||
@ -478,13 +478,13 @@ private:
|
||||
const Common::MACAddress& ResolveAddress(u32 inet_ip);
|
||||
};
|
||||
|
||||
#if !defined(__ANDROID__) && !defined(__APPLE__)
|
||||
|
||||
class IPCBBAInterface : public NetworkInterface
|
||||
{
|
||||
public:
|
||||
explicit IPCBBAInterface(CEXIETHERNET* const eth_ref) : NetworkInterface(eth_ref) {}
|
||||
|
||||
#if defined(WIN32) || (defined(__linux__) && !defined(__ANDROID__))
|
||||
|
||||
bool Activate() override;
|
||||
void Deactivate() override;
|
||||
bool IsActivated() override;
|
||||
@ -501,9 +501,50 @@ private:
|
||||
std::thread m_read_thread;
|
||||
Common::Flag m_read_enabled;
|
||||
Common::Flag m_read_thread_shutdown;
|
||||
};
|
||||
|
||||
#elif defined(__APPLE__)
|
||||
|
||||
class IPCBBAInterface : public NetworkInterface
|
||||
{
|
||||
public:
|
||||
explicit IPCBBAInterface(CEXIETHERNET* eth_ref);
|
||||
~IPCBBAInterface() override;
|
||||
|
||||
bool Activate() override;
|
||||
void Deactivate() override;
|
||||
bool IsActivated() override;
|
||||
bool SendFrame(const u8* frame, u32 size) override;
|
||||
bool RecvInit() override;
|
||||
void RecvStart() override;
|
||||
void RecvStop() override;
|
||||
|
||||
private:
|
||||
void ReadThreadHandler();
|
||||
void ProxyThreadHandler();
|
||||
|
||||
bool m_active{};
|
||||
void* m_context{};
|
||||
void* m_publisher{};
|
||||
void* m_subscriber{};
|
||||
std::thread m_read_thread;
|
||||
Common::Flag m_read_enabled;
|
||||
Common::Flag m_read_thread_shutdown;
|
||||
|
||||
std::thread m_proxy_thread;
|
||||
Common::Flag m_proxy_thread_shutdown;
|
||||
std::mutex m_proxy_mutex;
|
||||
void* m_proxy_publisher{};
|
||||
void* m_proxy_subscriber{};
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
class IPCBBAInterface : public NetworkInterface
|
||||
{
|
||||
public:
|
||||
explicit IPCBBAInterface(CEXIETHERNET* const eth_ref) : NetworkInterface(eth_ref) {}
|
||||
|
||||
bool Activate() override { return false; }
|
||||
void Deactivate() override {}
|
||||
bool IsActivated() override { return false; }
|
||||
@ -511,9 +552,9 @@ private:
|
||||
bool RecvInit() override { return false; }
|
||||
void RecvStart() override {}
|
||||
void RecvStop() override {}
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
std::unique_ptr<NetworkInterface> m_network_interface;
|
||||
|
||||
|
||||
@ -143,9 +143,7 @@ void GameCubePane::CreateWidgets()
|
||||
EXIDeviceType::EthernetXLink,
|
||||
EXIDeviceType::EthernetTapServer,
|
||||
EXIDeviceType::EthernetBuiltIn,
|
||||
#if defined(WIN32) || (defined(__linux__) && !defined(__ANDROID__))
|
||||
EXIDeviceType::EthernetIPC,
|
||||
#endif
|
||||
EXIDeviceType::ModemTapServer,
|
||||
})
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user