get things in a startable state

This commit is contained in:
Arisotura 2024-08-11 12:46:44 +02:00
parent a35865620f
commit a985478979
8 changed files with 262 additions and 172 deletions

View File

@ -24,18 +24,11 @@
#include <enet/enet.h> #include <enet/enet.h>
#include <QStandardItemModel> #include <QStandardItemModel>
#include <QProcess>
#include "NDS.h"
#include "NDSCart.h"
#include "main.h"
//#include "IPC.h"
#include "NetplayDialog.h" #include "NetplayDialog.h"
//#include "Input.h"
//#include "ROMManager.h"
#include "Config.h" #include "Config.h"
#include "Savestate.h" #include "main.h"
#include "Platform.h" #include "Netplay.h"
#include "ui_NetplayStartHostDialog.h" #include "ui_NetplayStartHostDialog.h"
#include "ui_NetplayStartClientDialog.h" #include "ui_NetplayStartClientDialog.h"
@ -44,8 +37,9 @@
using namespace melonDS; using namespace melonDS;
extern EmuThread* emuThread; NetplayDialog* netplayDlg = nullptr;
NetplayDialog* netplayDlg;
#define netplay() ((Netplay&)MPInterface::Get())
NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartHostDialog) NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent), ui(new Ui::NetplayStartHostDialog)
@ -53,6 +47,8 @@ NetplayStartHostDialog::NetplayStartHostDialog(QWidget* parent) : QDialog(parent
ui->setupUi(this); ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setMPInterface(MPInterface_Netplay);
ui->txtPort->setText("8064"); ui->txtPort->setText("8064");
} }
@ -72,7 +68,11 @@ void NetplayStartHostDialog::done(int r)
netplayDlg = NetplayDialog::openDlg(parentWidget()); netplayDlg = NetplayDialog::openDlg(parentWidget());
Netplay::StartHost(player.c_str(), port); netplay().StartHost(player.c_str(), port);
}
else
{
setMPInterface(MPInterface_Local);
} }
QDialog::done(r); QDialog::done(r);
@ -84,6 +84,8 @@ NetplayStartClientDialog::NetplayStartClientDialog(QWidget* parent) : QDialog(pa
ui->setupUi(this); ui->setupUi(this);
setAttribute(Qt::WA_DeleteOnClose); setAttribute(Qt::WA_DeleteOnClose);
setMPInterface(MPInterface_Netplay);
ui->txtPort->setText("8064"); ui->txtPort->setText("8064");
} }
@ -104,7 +106,11 @@ void NetplayStartClientDialog::done(int r)
netplayDlg = NetplayDialog::openDlg(parentWidget()); netplayDlg = NetplayDialog::openDlg(parentWidget());
Netplay::StartClient(player.c_str(), host.c_str(), port); netplay().StartClient(player.c_str(), host.c_str(), port);
}
else
{
setMPInterface(MPInterface_Local);
} }
QDialog::done(r); QDialog::done(r);
@ -119,50 +125,55 @@ NetplayDialog::NetplayDialog(QWidget* parent) : QDialog(parent), ui(new Ui::Netp
QStandardItemModel* model = new QStandardItemModel(); QStandardItemModel* model = new QStandardItemModel();
ui->tvPlayerList->setModel(model); ui->tvPlayerList->setModel(model);
connect(this, &NetplayDialog::sgUpdatePlayerList, this, &NetplayDialog::doUpdatePlayerList); timerID = startTimer(1000);
} }
NetplayDialog::~NetplayDialog() NetplayDialog::~NetplayDialog()
{ {
killTimer(timerID);
delete ui; delete ui;
} }
void NetplayDialog::done(int r) void NetplayDialog::done(int r)
{ {
// ??? // TODO
QDialog::done(r); QDialog::done(r);
} }
void NetplayDialog::updatePlayerList(Netplay::Player* players, int num) void NetplayDialog::timerEvent(QTimerEvent *event)
{ {
emit sgUpdatePlayerList(players, num); doUpdatePlayerList();
} }
void NetplayDialog::doUpdatePlayerList(Netplay::Player* players, int num) void NetplayDialog::doUpdatePlayerList()
{ {
auto playerlist = netplay().GetPlayerList();
int numplayers = playerlist.size();
auto maxplayers = netplay().GetMaxPlayers();
QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model(); QStandardItemModel* model = (QStandardItemModel*)ui->tvPlayerList->model();
model->clear(); model->clear();
model->setRowCount(num); model->setRowCount(numplayers);
// TODO: remove IP column in final product // TODO: remove IP column in final product
const QStringList header = {"#", "Player", "Status", "Ping", "IP"}; const QStringList header = {"#", "Player", "Status", "Ping", "IP"};
model->setHorizontalHeaderLabels(header); model->setHorizontalHeaderLabels(header);
for (int i = 0; i < num; i++) int i = 0;
for (const auto& player : playerlist)
{ {
Netplay::Player* player = &players[i]; QString id = QString("%0").arg(player.ID+1);
QString id = QString("%0").arg(player->ID+1);
model->setItem(i, 0, new QStandardItem(id)); model->setItem(i, 0, new QStandardItem(id));
QString name = player->Name; QString name = player.Name;
model->setItem(i, 1, new QStandardItem(name)); model->setItem(i, 1, new QStandardItem(name));
QString status; QString status;
switch (player->Status) switch (player.Status)
{ {
case 1: status = ""; break; case 1: status = ""; break;
case 2: status = "Host"; break; case 2: status = "Host"; break;
@ -174,8 +185,10 @@ void NetplayDialog::doUpdatePlayerList(Netplay::Player* players, int num)
model->setItem(i, 3, new QStandardItem("x")); model->setItem(i, 3, new QStandardItem("x"));
char ip[32]; char ip[32];
u32 addr = player->Address; u32 addr = player.Address;
sprintf(ip, "%d.%d.%d.%d", addr&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF, addr>>24); sprintf(ip, "%d.%d.%d.%d", addr&0xFF, (addr>>8)&0xFF, (addr>>16)&0xFF, addr>>24);
model->setItem(i, 4, new QStandardItem(ip)); model->setItem(i, 4, new QStandardItem(ip));
i++;
} }
} }

View File

@ -94,18 +94,17 @@ public:
return dlg; return dlg;
} }
void updatePlayerList(Netplay::Player* players, int num); protected:
void timerEvent(QTimerEvent* event) override;
signals:
void sgUpdatePlayerList(Netplay::Player* players, int num);
private slots: private slots:
void done(int r); void done(int r);
void doUpdatePlayerList(Netplay::Player* players, int num); void doUpdatePlayerList();
private: private:
Ui::NetplayDialog* ui; Ui::NetplayDialog* ui;
int timerID;
}; };
#endif // NETPLAYDIALOG_H #endif // NETPLAYDIALOG_H

View File

@ -75,6 +75,7 @@
#include "Savestate.h" #include "Savestate.h"
#include "MPInterface.h" #include "MPInterface.h"
#include "LANDialog.h" #include "LANDialog.h"
#include "NetplayDialog.h"
//#include "main_shaders.h" //#include "main_shaders.h"
@ -1705,14 +1706,14 @@ void MainWindow::onLANStartClient()
void MainWindow::onNPStartHost() void MainWindow::onNPStartHost()
{ {
//Netplay::StartHost(); if (!netplayWarning(true)) return;
//NetplayStartHostDialog::openDlg(this); NetplayStartHostDialog::openDlg(this);
} }
void MainWindow::onNPStartClient() void MainWindow::onNPStartClient()
{ {
//Netplay::StartClient(); if (!netplayWarning(false)) return;
//NetplayStartClientDialog::openDlg(this); NetplayStartClientDialog::openDlg(this);
} }
void MainWindow::onNPTest() void MainWindow::onNPTest()
@ -1752,6 +1753,15 @@ bool MainWindow::lanWarning(bool host)
return true; return true;
} }
bool MainWindow::netplayWarning(bool host)
{
// TODO
// * if a game is running it needs to be closed
// * if multiple instances are open they need to be closed
return true;
}
void MainWindow::onOpenEmuSettings() void MainWindow::onOpenEmuSettings()
{ {
emuThread->emuPause(); emuThread->emuPause();

View File

@ -242,6 +242,7 @@ private:
void createScreenPanel(); void createScreenPanel();
bool lanWarning(bool host); bool lanWarning(bool host);
bool netplayWarning(bool host);
bool showOSD; bool showOSD;

View File

@ -59,6 +59,8 @@ LocalMP::~LocalMP() noexcept
} }
Mutex_Free(MPQueueLock); Mutex_Free(MPQueueLock);
Log(LogLevel::Info, "MP comm deinited\n");
} }
void LocalMP::Begin(int inst) void LocalMP::Begin(int inst)

View File

@ -19,6 +19,7 @@
#include "MPInterface.h" #include "MPInterface.h"
#include "LocalMP.h" #include "LocalMP.h"
#include "LAN.h" #include "LAN.h"
#include "Netplay.h"
namespace melonDS namespace melonDS
{ {
@ -47,6 +48,8 @@ MPInterfaceType MPInterface::CurrentType = MPInterface_Dummy;
void MPInterface::Set(MPInterfaceType type) void MPInterface::Set(MPInterfaceType type)
{ {
Current = nullptr;
switch (type) switch (type)
{ {
case MPInterface_Local: case MPInterface_Local:
@ -57,6 +60,10 @@ void MPInterface::Set(MPInterfaceType type)
Current = std::make_unique<LAN>(); Current = std::make_unique<LAN>();
break; break;
case MPInterface_Netplay:
Current = std::make_unique<Netplay>();
break;
default: default:
Current = std::make_unique<DummyMP>(); Current = std::make_unique<DummyMP>();
break; break;

View File

@ -33,95 +33,83 @@
#include "Savestate.h" #include "Savestate.h"
#include "Platform.h" #include "Platform.h"
using namespace melonDS;
namespace Netplay namespace melonDS
{ {
bool Active; const u32 kLocalhost = 0x0100007F;
bool IsHost;
bool IsMirror;
ENetHost* Host;
ENetHost* MirrorHost;
Player Players[16];
int NumPlayers;
Player MyPlayer;
u32 HostAddress;
bool Lag;
int NumMirrorClients;
struct InputFrame
{
u32 FrameNum;
u32 KeyMask;
u32 Touching;
u32 TouchX, TouchY;
};
std::queue<InputFrame> InputQueue;
enum
{
Blob_CartROM = 0,
Blob_CartSRAM,
Blob_InitState,
Blob_MAX
};
const u32 kChunkSize = 0x10000;
u8 ChunkBuffer[0x10 + kChunkSize];
u8* Blobs[Blob_MAX];
u32 BlobLens[Blob_MAX];
int CurBlobType;
u32 CurBlobLen;
bool Init() Netplay::Netplay() noexcept : LocalMP(), Inited(false)
{ {
Active = false; Active = false;
IsHost = false; IsHost = false;
IsMirror = false;
Host = nullptr; Host = nullptr;
MirrorHost = nullptr;
Lag = false; Lag = false;
PlayersMutex = Platform::Mutex_Create();
memset(RemotePeers, 0, sizeof(RemotePeers));
memset(Players, 0, sizeof(Players)); memset(Players, 0, sizeof(Players));
NumPlayers = 0; NumPlayers = 0;
MaxPlayers = 0;
NumMirrorClients = 0; // TODO make this somewhat nicer
if (enet_initialize() != 0)
for (int i = 0; i < Blob_MAX; i++)
{ {
Blobs[i] = nullptr; Platform::Log(Platform::LogLevel::Error, "Netplay: failed to initialize enet\n");
BlobLens[i] = 0; return;
}
CurBlobType = -1;
CurBlobLen = 0;
/*if (enet_initialize() != 0)
{
printf("enet shat itself :(\n");
return false;
} }
printf("enet init OK\n");*/ Platform::Log(Platform::LogLevel::Info, "Netplay: enet initialized\n");
return true; Inited = true;
} }
void DeInit() Netplay::~Netplay()
{ {
// TODO: cleanup resources properly!! EndSession();
//enet_deinitialize(); Inited = false;
enet_deinitialize();
Platform::Mutex_Free(PlayersMutex);
Platform::Log(Platform::LogLevel::Info, "Netplay: enet deinitialized\n");
} }
void StartHost(const char* playername, int port) std::vector<Netplay::Player> Netplay::GetPlayerList()
{
Platform::Mutex_Lock(PlayersMutex);
std::vector<Player> ret;
for (int i = 0; i < 16; i++)
{
if (Players[i].Status == Player_None) continue;
// make a copy of the player entry, fix up the address field
Player newp = Players[i];
if (newp.ID == MyPlayer.ID)
{
newp.IsLocalPlayer = true;
newp.Address = kLocalhost;
}
else
{
newp.IsLocalPlayer = false;
if (newp.Status == Player_Host)
newp.Address = HostAddress;
}
ret.push_back(newp);
}
Platform::Mutex_Unlock(PlayersMutex);
return ret;
}
bool Netplay::StartHost(const char* playername, int port)
{ {
ENetAddress addr; ENetAddress addr;
addr.host = ENET_HOST_ANY; addr.host = ENET_HOST_ANY;
@ -131,7 +119,7 @@ void StartHost(const char* playername, int port)
if (!Host) if (!Host)
{ {
printf("host shat itself :(\n"); printf("host shat itself :(\n");
return; return false;
} }
Player* player = &Players[0]; Player* player = &Players[0];
@ -145,7 +133,7 @@ void StartHost(const char* playername, int port)
HostAddress = 0x0100007F; HostAddress = 0x0100007F;
NumMirrorClients = 0; /*NumMirrorClients = 0;
ENetAddress mirroraddr; ENetAddress mirroraddr;
mirroraddr.host = ENET_HOST_ANY; mirroraddr.host = ENET_HOST_ANY;
@ -155,23 +143,24 @@ printf("host mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr.p
if (!MirrorHost) if (!MirrorHost)
{ {
printf("mirror host shat itself :(\n"); printf("mirror host shat itself :(\n");
return; return false;
} }*/
Active = true; Active = true;
IsHost = true; IsHost = true;
IsMirror = false; //IsMirror = false;
//netplayDlg->updatePlayerList(Players, NumPlayers); //netplayDlg->updatePlayerList(Players, NumPlayers);
return true;
} }
void StartClient(const char* playername, const char* host, int port) bool Netplay::StartClient(const char* playername, const char* host, int port)
{ {
Host = enet_host_create(nullptr, 1, 1, 0, 0); Host = enet_host_create(nullptr, 1, 1, 0, 0);
if (!Host) if (!Host)
{ {
printf("client shat itself :(\n"); printf("client shat itself :(\n");
return; return false;
} }
printf("client created, connecting (%s, %s:%d)\n", playername, host, port); printf("client created, connecting (%s, %s:%d)\n", playername, host, port);
@ -183,7 +172,7 @@ void StartClient(const char* playername, const char* host, int port)
if (!peer) if (!peer)
{ {
printf("connect shat itself :(\n"); printf("connect shat itself :(\n");
return; return false;
} }
ENetEvent event; ENetEvent event;
@ -201,7 +190,7 @@ void StartClient(const char* playername, const char* host, int port)
{ {
printf("connection failed\n"); printf("connection failed\n");
enet_peer_reset(peer); enet_peer_reset(peer);
return; return false;
} }
Player* player = &MyPlayer; Player* player = &MyPlayer;
@ -214,10 +203,17 @@ void StartClient(const char* playername, const char* host, int port)
Active = true; Active = true;
IsHost = false; IsHost = false;
IsMirror = false; //IsMirror = false;
return true;
} }
void StartMirror(const Player* player) void Netplay::EndSession()
{
// todo
}
#if 0
void Netplay::StartMirror(const Player* player)
{ {
for (int i = 0; i < Blob_MAX; i++) for (int i = 0; i < Blob_MAX; i++)
{ {
@ -275,7 +271,7 @@ void StartMirror(const Player* player)
} }
u32 PlayerAddress(int id) u32 Netplay::PlayerAddress(int id)
{ {
if (id < 0 || id > 16) return 0; if (id < 0 || id > 16) return 0;
@ -285,9 +281,9 @@ u32 PlayerAddress(int id)
} }
bool SpawnMirrorInstance(Player player) bool Netplay::SpawnMirrorInstance(Player player)
{ {
#if 0
u16 curmask = IPC::GetInstanceBitmask(); u16 curmask = IPC::GetInstanceBitmask();
QProcess newinst; QProcess newinst;
@ -336,11 +332,11 @@ bool SpawnMirrorInstance(Player player)
if (player.Address == 0x0100007F) player.Address = HostAddress; if (player.Address == 0x0100007F) player.Address = HostAddress;
// calls Netplay::StartMirror() // calls Netplay::StartMirror()
//IPC::SendCommand(1<<newid, IPC::Cmd_SetupNetplayMirror, sizeof(Player), &player); //IPC::SendCommand(1<<newid, IPC::Cmd_SetupNetplayMirror, sizeof(Player), &player);
#endif
return true; return true;
} }
bool SendBlobToMirrorClients(int type, u32 len, u8* data) bool Netplay::SendBlobToMirrorClients(int type, u32 len, u8* data)
{ {
u8* buf = ChunkBuffer; u8* buf = ChunkBuffer;
@ -381,7 +377,7 @@ bool SendBlobToMirrorClients(int type, u32 len, u8* data)
return true; return true;
} }
void RecvBlobFromMirrorHost(ENetPeer* peer, ENetPacket* pkt) void Netplay::RecvBlobFromMirrorHost(ENetPeer* peer, ENetPacket* pkt)
{ {
u8* buf = pkt->data; u8* buf = pkt->data;
if (buf[0] == 0x01) if (buf[0] == 0x01)
@ -463,7 +459,7 @@ printf("[MC] finish blob type=%d len=%d\n", type, len);
if (pkt->dataLength != 2) return; if (pkt->dataLength != 2) return;
bool res = false; bool res = false;
#if 0
// reset // reset
NDS::SetConsoleType(buf[1]); NDS::SetConsoleType(buf[1]);
NDS::EjectCart(); NDS::EjectCart();
@ -488,10 +484,10 @@ printf("[MC] finish blob type=%d len=%d\n", type, len);
//LoadCheats(); //LoadCheats();
} }
#endif
// load initial state // load initial state
// TODO: terrible hack!! // TODO: terrible hack!!
#if 0
FILE* f = Platform::OpenFile("netplay2.mln", "wb"); FILE* f = Platform::OpenFile("netplay2.mln", "wb");
fwrite(Blobs[Blob_InitState], BlobLens[Blob_InitState], 1, f); fwrite(Blobs[Blob_InitState], BlobLens[Blob_InitState], 1, f);
fclose(f); fclose(f);
@ -513,7 +509,6 @@ printf("[MC] finish blob type=%d len=%d\n", type, len);
printf("[MC] state loaded, PC=%08X/%08X\n", NDS::GetPC(0), NDS::GetPC(1)); printf("[MC] state loaded, PC=%08X/%08X\n", NDS::GetPC(0), NDS::GetPC(1));
ENetPacket* resp = enet_packet_create(buf, 1, ENET_PACKET_FLAG_RELIABLE); ENetPacket* resp = enet_packet_create(buf, 1, ENET_PACKET_FLAG_RELIABLE);
enet_peer_send(peer, 1, resp); enet_peer_send(peer, 1, resp);
#endif
} }
else if (buf[0] == 0x05) else if (buf[0] == 0x05)
{ {
@ -522,11 +517,12 @@ printf("[MC] state loaded, PC=%08X/%08X\n", NDS::GetPC(0), NDS::GetPC(1));
} }
} }
void SyncMirrorClients()
void Netplay::SyncMirrorClients()
{ {
printf("[MIRROR HOST] syncing clients\n"); printf("[MIRROR HOST] syncing clients\n");
#if 0
SendBlobToMirrorClients(Blob_CartSRAM, NDSCart::GetSaveMemoryLength(), NDSCart::GetSaveMemory()); SendBlobToMirrorClients(Blob_CartSRAM, NDSCart::GetSaveMemoryLength(), NDSCart::GetSaveMemory());
// send initial state // send initial state
@ -586,10 +582,11 @@ void SyncMirrorClients()
//enet_host_flush(MirrorHost); //enet_host_flush(MirrorHost);
StartLocal(); StartLocal();
#endif
}
void StartGame() }
#endif
void Netplay::StartGame()
{ {
if (!IsHost) if (!IsHost)
{ {
@ -600,7 +597,7 @@ void StartGame()
// spawn mirror instances as needed // spawn mirror instances as needed
for (int i = 1; i < NumPlayers; i++) for (int i = 1; i < NumPlayers; i++)
{ {
SpawnMirrorInstance(Players[i]); //SpawnMirrorInstance(Players[i]);
} }
//SyncMirrorClients(); //SyncMirrorClients();
@ -623,7 +620,7 @@ void StartGame()
//StartLocal(); //StartLocal();
} }
void StartLocal() void Netplay::StartLocal()
{ {
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
@ -641,7 +638,7 @@ void StartLocal()
} }
void ProcessHost() void Netplay::ProcessHost()
{ {
if (!Host) return; if (!Host) return;
@ -730,7 +727,7 @@ void ProcessHost()
} }
} }
void ProcessClient() void Netplay::ProcessClient()
{ {
if (!Host) return; if (!Host) return;
@ -764,7 +761,7 @@ void ProcessClient()
NumMirrorClients = 0; NumMirrorClients = 0;
// create mirror host // create mirror host
ENetAddress mirroraddr; /*ENetAddress mirroraddr;
mirroraddr.host = ENET_HOST_ANY; mirroraddr.host = ENET_HOST_ANY;
mirroraddr.port = 8064+1 + data[1]; // FIXME!!!! mirroraddr.port = 8064+1 + data[1]; // FIXME!!!!
printf("client mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr.port); printf("client mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr.port);
@ -773,7 +770,7 @@ printf("client mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr
{ {
printf("mirror host shat itself :(\n"); printf("mirror host shat itself :(\n");
break; break;
} }*/
// send player information // send player information
MyPlayer.ID = data[1]; MyPlayer.ID = data[1];
@ -804,11 +801,11 @@ printf("client mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr
case 0x04: // start game case 0x04: // start game
{ {
// spawn mirror instances as needed // spawn mirror instances as needed
for (int i = 0; i < NumPlayers; i++) /*for (int i = 0; i < NumPlayers; i++)
{ {
if (i != MyPlayer.ID) if (i != MyPlayer.ID)
SpawnMirrorInstance(Players[i]); SpawnMirrorInstance(Players[i]);
} }*/
//SyncMirrorClients(); //SyncMirrorClients();
printf("bourf\n"); printf("bourf\n");
@ -826,10 +823,11 @@ printf("birf\n");
} }
} }
void ProcessMirrorHost() #if 0
void Netplay::ProcessMirrorHost()
{ {
if (!MirrorHost) return; if (!MirrorHost) return;
#if 0
bool block = false; bool block = false;
ENetEvent event; ENetEvent event;
while (enet_host_service(MirrorHost, &event, block ? 5000 : 0) > 0) while (enet_host_service(MirrorHost, &event, block ? 5000 : 0) > 0)
@ -915,13 +913,12 @@ void ProcessMirrorHost()
break; break;
} }
} }
#endif
} }
void ProcessMirrorClient() void Netplay::ProcessMirrorClient()
{ {
if (!MirrorHost) return; if (!MirrorHost) return;
#if 0
bool block = false; bool block = false;
if (emuThread->emuIsRunning())// && NDS::NumFrames > 4) if (emuThread->emuIsRunning())// && NDS::NumFrames > 4)
{ {
@ -982,16 +979,16 @@ printf("mirror client lag notify: %d\n", lag);
if (block) break; if (block) break;
} }
#endif
} }
#endif
void ProcessFrame() void Netplay::ProcessFrame()
{ {
if (IsMirror) /*if (IsMirror)
{ {
ProcessMirrorClient(); ProcessMirrorClient();
} }
else else*/
{ {
if (IsHost) if (IsHost)
{ {
@ -1002,11 +999,12 @@ void ProcessFrame()
ProcessClient(); ProcessClient();
} }
ProcessMirrorHost(); //ProcessMirrorHost();
} }
} }
void ProcessInput() #if 0
void Netplay::ProcessInput()
{ {
// netplay input processing // netplay input processing
// //
@ -1022,7 +1020,7 @@ void ProcessInput()
// apply each input to the frame it's assigned to // apply each input to the frame it's assigned to
// before running a frame, we need to wait to have received input for it // before running a frame, we need to wait to have received input for it
// TODO: alert host if we are running too far behind // TODO: alert host if we are running too far behind
#if 0
if (!IsMirror) if (!IsMirror)
{ {
u32 lag = 4; // TODO: make configurable!! u32 lag = 4; // TODO: make configurable!!
@ -1078,7 +1076,13 @@ void ProcessInput()
else NDS::ReleaseScreen(); else NDS::ReleaseScreen();
InputQueue.pop(); InputQueue.pop();
}
#endif #endif
void Netplay::Process()
{
ProcessFrame();
LocalMP::Process();
} }
} }

View File

@ -19,39 +19,93 @@
#ifndef NETPLAY_H #ifndef NETPLAY_H
#define NETPLAY_H #define NETPLAY_H
#include <queue>
#include <enet/enet.h>
#include "types.h" #include "types.h"
#include "Platform.h"
#include "LocalMP.h"
namespace Netplay namespace melonDS
{ {
struct Player // since netplay relies on local MP comm locally,
// we extend the LocalMP class to reuse its functionality
class Netplay : public LocalMP
{ {
int ID; public:
char Name[32]; Netplay() noexcept;
int Status; // 0=no player 1=normal 2=host 3=connecting Netplay(const Netplay&) = delete;
melonDS::u32 Address; Netplay& operator=(const Netplay&) = delete;
Netplay(Netplay&& other) = delete;
Netplay& operator=(Netplay&& other) = delete;
~Netplay() noexcept;
enum PlayerStatus
{
Player_None = 0, // no player in this entry
Player_Client, // game client
Player_Host, // game host
Player_Connecting, // player still connecting
Player_Disconnected, // player disconnected
};
struct Player
{
int ID;
char Name[32];
int Status; // 0=no player 1=normal 2=host 3=connecting
u32 Address;
bool IsLocalPlayer;
};
bool StartHost(const char* player, int port);
bool StartClient(const char* player, const char* host, int port);
void EndSession();
std::vector<Player> GetPlayerList();
int GetNumPlayers() { return NumPlayers; }
int GetMaxPlayers() { return MaxPlayers; }
void Process() override;
private:
bool Inited;
bool Active;
bool IsHost;
ENetHost* Host;
ENetPeer* RemotePeers[16];
Player Players[16];
int NumPlayers;
int MaxPlayers;
Platform::Mutex* PlayersMutex;
Player MyPlayer;
u32 HostAddress;
bool Lag;
int NumMirrorClients;
struct InputFrame
{
u32 FrameNum;
u32 KeyMask;
u32 Touching;
u32 TouchX, TouchY;
};
std::queue<InputFrame> InputQueue;
void StartGame();
void StartLocal();
void ProcessHost();
void ProcessClient();
void ProcessFrame();
}; };
extern bool Active;
bool Init();
void DeInit();
void StartHost(const char* player, int port);
void StartClient(const char* player, const char* host, int port);
void StartMirror(const Player* player);
melonDS::u32 PlayerAddress(int id);
void StartGame();
void StartLocal();
void StartGame();
void ProcessFrame();
void ProcessInput();
} }
#endif // NETPLAY_H #endif // NETPLAY_H