Merge pull request #5078 from lioncash/si

SI_DeviceGBA: Minor cleanup
This commit is contained in:
Markus Wick 2017-03-13 21:00:36 +01:00 committed by GitHub
commit f0c2bae778
2 changed files with 130 additions and 123 deletions

View File

@ -4,6 +4,7 @@
#include "Core/HW/SI/SI_DeviceGBA.h" #include "Core/HW/SI/SI_DeviceGBA.h"
#include <cstddef>
#include <memory> #include <memory>
#include <mutex> #include <mutex>
#include <queue> #include <queue>
@ -19,16 +20,15 @@
#include "Core/HW/SI/SI_Device.h" #include "Core/HW/SI/SI_Device.h"
#include "Core/HW/SystemTimers.h" #include "Core/HW/SystemTimers.h"
static std::thread connectionThread;
static std::queue<std::unique_ptr<sf::TcpSocket>> waiting_socks;
static std::queue<std::unique_ptr<sf::TcpSocket>> waiting_clocks;
static std::mutex cs_gba;
static std::mutex cs_gba_clk;
static u8 num_connected;
namespace namespace
{ {
Common::Flag server_running; std::thread s_connection_thread;
std::queue<std::unique_ptr<sf::TcpSocket>> s_waiting_socks;
std::queue<std::unique_ptr<sf::TcpSocket>> s_waiting_clocks;
std::mutex s_cs_gba;
std::mutex s_cs_gba_clk;
u8 s_num_connected;
Common::Flag s_server_running;
} }
enum EJoybusCmds enum EJoybusCmds
@ -44,7 +44,7 @@ const u64 BYTES_PER_SECOND = BITS_PER_SECOND / 8;
u8 GetNumConnected() u8 GetNumConnected()
{ {
int num_ports_connected = num_connected; int num_ports_connected = s_num_connected;
if (num_ports_connected == 0) if (num_ports_connected == 0)
num_ports_connected = 1; num_ports_connected = 1;
@ -87,7 +87,7 @@ int GetTransferTime(u8 cmd)
static void GBAConnectionWaiter() static void GBAConnectionWaiter()
{ {
server_running.Set(); s_server_running.Set();
Common::SetCurrentThreadName("GBA Connection Waiter"); Common::SetCurrentThreadName("GBA Connection Waiter");
@ -106,19 +106,19 @@ static void GBAConnectionWaiter()
clock_server.setBlocking(false); clock_server.setBlocking(false);
auto new_client = std::make_unique<sf::TcpSocket>(); auto new_client = std::make_unique<sf::TcpSocket>();
while (server_running.IsSet()) while (s_server_running.IsSet())
{ {
if (server.accept(*new_client) == sf::Socket::Done) if (server.accept(*new_client) == sf::Socket::Done)
{ {
std::lock_guard<std::mutex> lk(cs_gba); std::lock_guard<std::mutex> lk(s_cs_gba);
waiting_socks.push(std::move(new_client)); s_waiting_socks.push(std::move(new_client));
new_client = std::make_unique<sf::TcpSocket>(); new_client = std::make_unique<sf::TcpSocket>();
} }
if (clock_server.accept(*new_client) == sf::Socket::Done) if (clock_server.accept(*new_client) == sf::Socket::Done)
{ {
std::lock_guard<std::mutex> lk(cs_gba_clk); std::lock_guard<std::mutex> lk(s_cs_gba_clk);
waiting_clocks.push(std::move(new_client)); s_waiting_clocks.push(std::move(new_client));
new_client = std::make_unique<sf::TcpSocket>(); new_client = std::make_unique<sf::TcpSocket>();
} }
@ -129,21 +129,21 @@ static void GBAConnectionWaiter()
void GBAConnectionWaiter_Shutdown() void GBAConnectionWaiter_Shutdown()
{ {
server_running.Clear(); s_server_running.Clear();
if (connectionThread.joinable()) if (s_connection_thread.joinable())
connectionThread.join(); s_connection_thread.join();
} }
static bool GetAvailableSock(std::unique_ptr<sf::TcpSocket>& sock_to_fill) static bool GetAvailableSock(std::unique_ptr<sf::TcpSocket>& sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
std::lock_guard<std::mutex> lk(cs_gba); std::lock_guard<std::mutex> lk(s_cs_gba);
if (!waiting_socks.empty()) if (!s_waiting_socks.empty())
{ {
sock_to_fill = std::move(waiting_socks.front()); sock_to_fill = std::move(s_waiting_socks.front());
waiting_socks.pop(); s_waiting_socks.pop();
sock_filled = true; sock_filled = true;
} }
@ -154,28 +154,24 @@ static bool GetNextClock(std::unique_ptr<sf::TcpSocket>& sock_to_fill)
{ {
bool sock_filled = false; bool sock_filled = false;
std::lock_guard<std::mutex> lk(cs_gba_clk); std::lock_guard<std::mutex> lk(s_cs_gba_clk);
if (!waiting_clocks.empty()) if (!s_waiting_clocks.empty())
{ {
sock_to_fill = std::move(waiting_clocks.front()); sock_to_fill = std::move(s_waiting_clocks.front());
waiting_clocks.pop(); s_waiting_clocks.pop();
sock_filled = true; sock_filled = true;
} }
return sock_filled; return sock_filled;
} }
GBASockServer::GBASockServer(int _iDeviceNumber) GBASockServer::GBASockServer(int device_number) : m_device_number{device_number}
{ {
if (!connectionThread.joinable()) if (!s_connection_thread.joinable())
connectionThread = std::thread(GBAConnectionWaiter); s_connection_thread = std::thread(GBAConnectionWaiter);
cmd = 0; s_num_connected = 0;
num_connected = 0;
last_time_slice = 0;
booted = false;
device_number = _iDeviceNumber;
} }
GBASockServer::~GBASockServer() GBASockServer::~GBASockServer()
@ -185,108 +181,110 @@ GBASockServer::~GBASockServer()
void GBASockServer::Disconnect() void GBASockServer::Disconnect()
{ {
if (client) if (m_client)
{ {
num_connected--; s_num_connected--;
client->disconnect(); m_client->disconnect();
client = nullptr; m_client = nullptr;
} }
if (clock_sync) if (m_clock_sync)
{ {
clock_sync->disconnect(); m_clock_sync->disconnect();
clock_sync = nullptr; m_clock_sync = nullptr;
} }
last_time_slice = 0; m_last_time_slice = 0;
booted = false; m_booted = false;
} }
void GBASockServer::ClockSync() void GBASockServer::ClockSync()
{ {
if (!clock_sync) if (!m_clock_sync)
if (!GetNextClock(clock_sync)) if (!GetNextClock(m_clock_sync))
return; return;
u32 time_slice = 0; u32 time_slice = 0;
if (last_time_slice == 0) if (m_last_time_slice == 0)
{ {
num_connected++; s_num_connected++;
last_time_slice = CoreTiming::GetTicks(); m_last_time_slice = CoreTiming::GetTicks();
time_slice = (u32)(SystemTimers::GetTicksPerSecond() / 60); time_slice = (u32)(SystemTimers::GetTicksPerSecond() / 60);
} }
else else
{ {
time_slice = (u32)(CoreTiming::GetTicks() - last_time_slice); time_slice = (u32)(CoreTiming::GetTicks() - m_last_time_slice);
} }
time_slice = (u32)((u64)time_slice * 16777216 / SystemTimers::GetTicksPerSecond()); time_slice = (u32)((u64)time_slice * 16777216 / SystemTimers::GetTicksPerSecond());
last_time_slice = CoreTiming::GetTicks(); m_last_time_slice = CoreTiming::GetTicks();
char bytes[4] = {0, 0, 0, 0}; char bytes[4] = {0, 0, 0, 0};
bytes[0] = (time_slice >> 24) & 0xff; bytes[0] = (time_slice >> 24) & 0xff;
bytes[1] = (time_slice >> 16) & 0xff; bytes[1] = (time_slice >> 16) & 0xff;
bytes[2] = (time_slice >> 8) & 0xff; bytes[2] = (time_slice >> 8) & 0xff;
bytes[3] = time_slice & 0xff; bytes[3] = time_slice & 0xff;
sf::Socket::Status status = clock_sync->send(bytes, 4); sf::Socket::Status status = m_clock_sync->send(bytes, 4);
if (status == sf::Socket::Disconnected) if (status == sf::Socket::Disconnected)
{ {
clock_sync->disconnect(); m_clock_sync->disconnect();
clock_sync = nullptr; m_clock_sync = nullptr;
} }
} }
void GBASockServer::Send(const u8* si_buffer) void GBASockServer::Send(const u8* si_buffer)
{ {
if (!client) if (!m_client)
if (!GetAvailableSock(client)) if (!GetAvailableSock(m_client))
return; return;
for (int i = 0; i < 5; i++) for (size_t i = 0; i < m_send_data.size(); i++)
send_data[i] = si_buffer[i ^ 3]; m_send_data[i] = si_buffer[i ^ 3];
cmd = (u8)send_data[0]; m_cmd = (u8)m_send_data[0];
#ifdef _DEBUG #ifdef _DEBUG
NOTICE_LOG(SERIALINTERFACE, "%01d cmd %02x [> %02x%02x%02x%02x]", device_number, (u8)send_data[0], NOTICE_LOG(SERIALINTERFACE, "%01d cmd %02x [> %02x%02x%02x%02x]", m_device_number,
(u8)send_data[1], (u8)send_data[2], (u8)send_data[3], (u8)send_data[4]); (u8)m_send_data[0], (u8)m_send_data[1], (u8)m_send_data[2], (u8)m_send_data[3],
(u8)m_send_data[4]);
#endif #endif
client->setBlocking(false); m_client->setBlocking(false);
sf::Socket::Status status; sf::Socket::Status status;
if (cmd == CMD_WRITE) if (m_cmd == CMD_WRITE)
status = client->send(send_data, sizeof(send_data)); status = m_client->send(m_send_data.data(), m_send_data.size());
else else
status = client->send(send_data, 1); status = m_client->send(m_send_data.data(), 1);
if (cmd != CMD_STATUS) if (m_cmd != CMD_STATUS)
booted = true; m_booted = true;
if (status == sf::Socket::Disconnected) if (status == sf::Socket::Disconnected)
Disconnect(); Disconnect();
time_cmd_sent = CoreTiming::GetTicks(); m_time_cmd_sent = CoreTiming::GetTicks();
} }
int GBASockServer::Receive(u8* si_buffer) int GBASockServer::Receive(u8* si_buffer)
{ {
if (!client) if (!m_client)
if (!GetAvailableSock(client)) if (!GetAvailableSock(m_client))
return 5; return 5;
size_t num_received = 0; size_t num_received = 0;
u64 transferTime = GetTransferTime((u8)send_data[0]); u64 transfer_time = GetTransferTime((u8)m_send_data[0]);
bool block = (CoreTiming::GetTicks() - time_cmd_sent) > transferTime; bool block = (CoreTiming::GetTicks() - m_time_cmd_sent) > transfer_time;
if (cmd == CMD_STATUS && !booted) if (m_cmd == CMD_STATUS && !m_booted)
block = false; block = false;
if (block) if (block)
{ {
sf::SocketSelector Selector; sf::SocketSelector selector;
Selector.add(*client); selector.add(*m_client);
Selector.wait(sf::milliseconds(1000)); selector.wait(sf::milliseconds(1000));
} }
sf::Socket::Status recv_stat = client->receive(recv_data, sizeof(recv_data), num_received); sf::Socket::Status recv_stat =
m_client->receive(m_recv_data.data(), m_recv_data.size(), num_received);
if (recv_stat == sf::Socket::Disconnected) if (recv_stat == sf::Socket::Disconnected)
{ {
Disconnect(); Disconnect();
@ -296,37 +294,36 @@ int GBASockServer::Receive(u8* si_buffer)
if (recv_stat == sf::Socket::NotReady) if (recv_stat == sf::Socket::NotReady)
num_received = 0; num_received = 0;
if (num_received > sizeof(recv_data)) if (num_received > m_recv_data.size())
num_received = sizeof(recv_data); num_received = m_recv_data.size();
if (num_received > 0) if (num_received > 0)
{ {
#ifdef _DEBUG #ifdef _DEBUG
if ((u8)send_data[0] == 0x00 || (u8)send_data[0] == 0xff) if ((u8)m_send_data[0] == 0x00 || (u8)m_send_data[0] == 0xff)
{ {
WARN_LOG(SERIALINTERFACE, "%01d [< %02x%02x%02x%02x%02x] (%lu)", WARN_LOG(SERIALINTERFACE, "%01d [< %02x%02x%02x%02x%02x] (%zu)",
device_number, (u8)recv_data[0], (u8)recv_data[1], (u8)recv_data[2], m_device_number, (u8)m_recv_data[0], (u8)m_recv_data[1], (u8)m_recv_data[2],
(u8)recv_data[3], (u8)recv_data[4], num_received); (u8)m_recv_data[3], (u8)m_recv_data[4], num_received);
} }
else else
{ {
ERROR_LOG(SERIALINTERFACE, "%01d [< %02x%02x%02x%02x%02x] (%lu)", ERROR_LOG(SERIALINTERFACE, "%01d [< %02x%02x%02x%02x%02x] (%zu)",
device_number, (u8)recv_data[0], (u8)recv_data[1], (u8)recv_data[2], m_device_number, (u8)m_recv_data[0], (u8)m_recv_data[1], (u8)m_recv_data[2],
(u8)recv_data[3], (u8)recv_data[4], num_received); (u8)m_recv_data[3], (u8)m_recv_data[4], num_received);
} }
#endif #endif
for (int i = 0; i < 5; i++) for (size_t i = 0; i < m_recv_data.size(); i++)
si_buffer[i ^ 3] = recv_data[i]; si_buffer[i ^ 3] = m_recv_data[i];
} }
return (int)num_received; return (int)num_received;
} }
CSIDevice_GBA::CSIDevice_GBA(SIDevices _device, int _iDeviceNumber) CSIDevice_GBA::CSIDevice_GBA(SIDevices device, int device_number)
: ISIDevice(_device, _iDeviceNumber), GBASockServer(_iDeviceNumber) : ISIDevice(device, device_number), GBASockServer(device_number)
{ {
waiting_for_response = false;
} }
CSIDevice_GBA::~CSIDevice_GBA() CSIDevice_GBA::~CSIDevice_GBA()
@ -334,38 +331,47 @@ CSIDevice_GBA::~CSIDevice_GBA()
GBASockServer::Disconnect(); GBASockServer::Disconnect();
} }
int CSIDevice_GBA::RunBuffer(u8* _pBuffer, int _iLength) int CSIDevice_GBA::RunBuffer(u8* buffer, int length)
{ {
if (!waiting_for_response) if (!m_waiting_for_response)
{ {
for (int i = 0; i < 5; i++) for (size_t i = 0; i < m_send_data.size(); i++)
send_data[i] = _pBuffer[i ^ 3]; m_send_data[i] = buffer[i ^ 3];
num_data_received = 0; m_num_data_received = 0;
ClockSync(); ClockSync();
Send(_pBuffer); Send(buffer);
timestamp_sent = CoreTiming::GetTicks(); m_timestamp_sent = CoreTiming::GetTicks();
waiting_for_response = true; m_waiting_for_response = true;
} }
if (waiting_for_response && num_data_received == 0) if (m_waiting_for_response && m_num_data_received == 0)
{ {
num_data_received = Receive(_pBuffer); m_num_data_received = Receive(buffer);
} }
if ((GetTransferTime(send_data[0])) > (int)(CoreTiming::GetTicks() - timestamp_sent)) if ((GetTransferTime(m_send_data[0])) > (int)(CoreTiming::GetTicks() - m_timestamp_sent))
{ {
return 0; return 0;
} }
else else
{ {
if (num_data_received != 0) if (m_num_data_received != 0)
waiting_for_response = false; m_waiting_for_response = false;
return num_data_received; return m_num_data_received;
} }
} }
int CSIDevice_GBA::TransferInterval() int CSIDevice_GBA::TransferInterval()
{ {
return GetTransferTime(send_data[0]); return GetTransferTime(m_send_data[0]);
}
bool CSIDevice_GBA::GetData(u32& hi, u32& low)
{
return false;
}
void CSIDevice_GBA::SendCommand(u32 command, u8 poll)
{
} }

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <array>
#include <memory> #include <memory>
#include <SFML/Network.hpp> #include <SFML/Network.hpp>
@ -20,7 +21,7 @@ void GBAConnectionWaiter_Shutdown();
class GBASockServer class GBASockServer
{ {
public: public:
GBASockServer(int _iDeviceNumber); explicit GBASockServer(int device_number);
~GBASockServer(); ~GBASockServer();
void Disconnect(); void Disconnect();
@ -31,32 +32,32 @@ public:
int Receive(u8* si_buffer); int Receive(u8* si_buffer);
private: private:
std::unique_ptr<sf::TcpSocket> client; std::unique_ptr<sf::TcpSocket> m_client;
std::unique_ptr<sf::TcpSocket> clock_sync; std::unique_ptr<sf::TcpSocket> m_clock_sync;
char send_data[5]; std::array<char, 5> m_send_data{};
char recv_data[5]; std::array<char, 5> m_recv_data{};
u64 time_cmd_sent; u64 m_time_cmd_sent = 0;
u64 last_time_slice; u64 m_last_time_slice = 0;
u8 device_number; int m_device_number;
u8 cmd; u8 m_cmd = 0;
bool booted; bool m_booted = false;
}; };
class CSIDevice_GBA : public ISIDevice, private GBASockServer class CSIDevice_GBA : public ISIDevice, private GBASockServer
{ {
public: public:
CSIDevice_GBA(SIDevices device, int _iDeviceNumber); CSIDevice_GBA(SIDevices device, int device_number);
~CSIDevice_GBA(); ~CSIDevice_GBA();
int RunBuffer(u8* _pBuffer, int _iLength) override; int RunBuffer(u8* buffer, int length) override;
int TransferInterval() override; int TransferInterval() override;
bool GetData(u32& hi, u32& low) override;
void SendCommand(u32 command, u8 poll) override;
bool GetData(u32& _Hi, u32& _Low) override { return false; }
void SendCommand(u32 _Cmd, u8 _Poll) override {}
private: private:
u8 send_data[5]; std::array<u8, 5> m_send_data{};
int num_data_received; int m_num_data_received = 0;
u64 timestamp_sent; u64 m_timestamp_sent = 0;
bool waiting_for_response; bool m_waiting_for_response = false;
}; };