begin work on state sync
This commit is contained in:
parent
586b2d4984
commit
db09e0da9f
|
@ -27,11 +27,13 @@
|
||||||
#include <QProcess>
|
#include <QProcess>
|
||||||
|
|
||||||
#include "NDS.h"
|
#include "NDS.h"
|
||||||
|
#include "NDSCart.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "IPC.h"
|
#include "IPC.h"
|
||||||
#include "Netplay.h"
|
#include "Netplay.h"
|
||||||
#include "Input.h"
|
#include "Input.h"
|
||||||
#include "ROMManager.h"
|
#include "ROMManager.h"
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
#include "ui_NetplayStartHostDialog.h"
|
#include "ui_NetplayStartHostDialog.h"
|
||||||
#include "ui_NetplayStartClientDialog.h"
|
#include "ui_NetplayStartClientDialog.h"
|
||||||
|
@ -202,6 +204,21 @@ struct InputFrame
|
||||||
|
|
||||||
std::queue<InputFrame> InputQueue;
|
std::queue<InputFrame> InputQueue;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Blob_CartROM = 0,
|
||||||
|
Blob_CartSRAM,
|
||||||
|
|
||||||
|
Blob_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
const u32 kChunkSize = 0x10000;
|
||||||
|
u8 ChunkBuffer[0x10 + kChunkSize];
|
||||||
|
u8* Blobs[Blob_MAX];
|
||||||
|
u32 BlobLens[Blob_MAX];
|
||||||
|
int CurBlobType;
|
||||||
|
u32 CurBlobLen;
|
||||||
|
|
||||||
|
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
|
@ -215,6 +232,14 @@ bool Init()
|
||||||
memset(Players, 0, sizeof(Players));
|
memset(Players, 0, sizeof(Players));
|
||||||
NumPlayers = 0;
|
NumPlayers = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < Blob_MAX; i++)
|
||||||
|
{
|
||||||
|
Blobs[i] = nullptr;
|
||||||
|
BlobLens[i] = 0;
|
||||||
|
}
|
||||||
|
CurBlobType = -1;
|
||||||
|
CurBlobLen = 0;
|
||||||
|
|
||||||
if (enet_initialize() != 0)
|
if (enet_initialize() != 0)
|
||||||
{
|
{
|
||||||
printf("enet shat itself :(\n");
|
printf("enet shat itself :(\n");
|
||||||
|
@ -329,7 +354,15 @@ void StartClient(const char* playername, const char* host, int port)
|
||||||
|
|
||||||
void StartMirror(const Player* player)
|
void StartMirror(const Player* player)
|
||||||
{
|
{
|
||||||
MirrorHost = enet_host_create(nullptr, 1, 1, 0, 0);
|
for (int i = 0; i < Blob_MAX; i++)
|
||||||
|
{
|
||||||
|
Blobs[i] = nullptr;
|
||||||
|
BlobLens[i] = 0;
|
||||||
|
}
|
||||||
|
CurBlobType = -1;
|
||||||
|
CurBlobLen = 0;
|
||||||
|
|
||||||
|
MirrorHost = enet_host_create(nullptr, 1, 2, 0, 0);
|
||||||
if (!MirrorHost)
|
if (!MirrorHost)
|
||||||
{
|
{
|
||||||
printf("mirror shat itself :(\n");
|
printf("mirror shat itself :(\n");
|
||||||
|
@ -416,7 +449,7 @@ bool SpawnMirrorInstance(Player player)
|
||||||
if (newmask == curmask) continue;
|
if (newmask == curmask) continue;
|
||||||
|
|
||||||
newmask &= ~curmask;
|
newmask &= ~curmask;
|
||||||
for (int id = 0; id < 32; id++)
|
for (int id = 0; id < 16; id++)
|
||||||
{
|
{
|
||||||
if (newmask & (1 << id))
|
if (newmask & (1 << id))
|
||||||
{
|
{
|
||||||
|
@ -431,8 +464,8 @@ bool SpawnMirrorInstance(Player player)
|
||||||
// setup that instance
|
// setup that instance
|
||||||
printf("netplay: spawned mirror instance for player %d with ID %d, configuring\n", player.ID, newid);
|
printf("netplay: spawned mirror instance for player %d with ID %d, configuring\n", player.ID, newid);
|
||||||
|
|
||||||
std::string rompath = ROMManager::FullROMPath.join('|').toStdString();
|
//std::string rompath = ROMManager::FullROMPath.join('|').toStdString();
|
||||||
IPC::SendCommandStr(1<<newid, IPC::Cmd_LoadROM, rompath);
|
//IPC::SendCommandStr(1<<newid, IPC::Cmd_LoadROM, rompath);
|
||||||
|
|
||||||
if (player.Address == 0x0100007F) player.Address = HostAddress;
|
if (player.Address == 0x0100007F) player.Address = HostAddress;
|
||||||
IPC::SendCommand(1<<newid, IPC::Cmd_SetupNetplayMirror, sizeof(Player), &player);
|
IPC::SendCommand(1<<newid, IPC::Cmd_SetupNetplayMirror, sizeof(Player), &player);
|
||||||
|
@ -440,6 +473,162 @@ bool SpawnMirrorInstance(Player player)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SendBlobToMirrorClients(int type, u32 len, u8* data)
|
||||||
|
{
|
||||||
|
u8* buf = ChunkBuffer;
|
||||||
|
|
||||||
|
buf[0] = 0x01;
|
||||||
|
buf[1] = type & 0xFF;
|
||||||
|
buf[2] = 0;
|
||||||
|
buf[3] = 0;
|
||||||
|
*(u32*)&buf[4] = len;
|
||||||
|
|
||||||
|
ENetPacket* pkt = enet_packet_create(buf, 8, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(MirrorHost, 1, pkt);
|
||||||
|
|
||||||
|
if (len > 0)
|
||||||
|
{
|
||||||
|
buf[0] = 0x02;
|
||||||
|
*(u32*)&buf[12] = 0;
|
||||||
|
|
||||||
|
for (u32 pos = 0; pos < len; pos += kChunkSize)
|
||||||
|
{
|
||||||
|
u32 chunklen = kChunkSize;
|
||||||
|
if ((pos + chunklen) > len)
|
||||||
|
chunklen = len - pos;
|
||||||
|
|
||||||
|
*(u32*)&buf[8] = pos;
|
||||||
|
memcpy(&buf[16], &data[pos], chunklen);
|
||||||
|
|
||||||
|
ENetPacket* pkt = enet_packet_create(buf, 16+chunklen, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(MirrorHost, 1, pkt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[0] = 0x03;
|
||||||
|
|
||||||
|
pkt = enet_packet_create(buf, 8, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(MirrorHost, 1, pkt);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RecvBlobFromMirrorHost(ENetPacket* pkt)
|
||||||
|
{
|
||||||
|
u8* buf = pkt->data;
|
||||||
|
if (buf[0] == 0x01)
|
||||||
|
{
|
||||||
|
if (CurBlobType != -1) return;
|
||||||
|
if (pkt->dataLength != 8) return;
|
||||||
|
|
||||||
|
int type = buf[1];
|
||||||
|
if (type > Blob_MAX) return;
|
||||||
|
|
||||||
|
u32 len = *(u32*)&buf[4];
|
||||||
|
if (len > 0x40000000) return;
|
||||||
|
|
||||||
|
if (Blobs[type] != nullptr) return;
|
||||||
|
if (BlobLens[type] != 0) return;
|
||||||
|
|
||||||
|
if (len) Blobs[type] = new u8[len];
|
||||||
|
BlobLens[type] = len;
|
||||||
|
|
||||||
|
CurBlobType = type;
|
||||||
|
CurBlobLen = len;
|
||||||
|
}
|
||||||
|
else if (buf[0] == 0x02)
|
||||||
|
{
|
||||||
|
if (CurBlobType < 0 || CurBlobType > Blob_MAX) return;
|
||||||
|
if (pkt->dataLength > (16+kChunkSize)) return;
|
||||||
|
|
||||||
|
int type = buf[1];
|
||||||
|
if (type != CurBlobType) return;
|
||||||
|
|
||||||
|
u32 len = *(u32*)&buf[4];
|
||||||
|
if (len != CurBlobLen) return;
|
||||||
|
|
||||||
|
u32 pos = *(u32*)&buf[8];
|
||||||
|
if (pos >= len) return;
|
||||||
|
if ((pos + (pkt->dataLength-16)) > len) return;
|
||||||
|
|
||||||
|
u8* dst = Blobs[type];
|
||||||
|
if (!dst) return;
|
||||||
|
if (BlobLens[type] != len) return;
|
||||||
|
|
||||||
|
memcpy(&dst[pos], &buf[16], pkt->dataLength-16);
|
||||||
|
}
|
||||||
|
else if (buf[0] == 0x03)
|
||||||
|
{
|
||||||
|
if (CurBlobType < 0 || CurBlobType > Blob_MAX) return;
|
||||||
|
if (pkt->dataLength != 8) return;
|
||||||
|
|
||||||
|
int type = buf[1];
|
||||||
|
if (type != CurBlobType) return;
|
||||||
|
|
||||||
|
u32 len = *(u32*)&buf[4];
|
||||||
|
if (len != CurBlobLen) return;
|
||||||
|
|
||||||
|
CurBlobType = -1;
|
||||||
|
CurBlobLen = 0;
|
||||||
|
}
|
||||||
|
else if (buf[0] == 0x04)
|
||||||
|
{
|
||||||
|
if (pkt->dataLength != 2) return;
|
||||||
|
|
||||||
|
bool res = false;
|
||||||
|
|
||||||
|
// reset
|
||||||
|
NDS::SetConsoleType(buf[1]);
|
||||||
|
NDS::EjectCart();
|
||||||
|
NDS::Reset();
|
||||||
|
//SetBatteryLevels();
|
||||||
|
|
||||||
|
if (Blobs[Blob_CartROM])
|
||||||
|
{
|
||||||
|
res = NDS::LoadCart(Blobs[Blob_CartROM], BlobLens[Blob_CartROM],
|
||||||
|
Blobs[Blob_CartSRAM], BlobLens[Blob_CartSRAM]);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
printf("!!!! FAIL!!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < Blob_MAX; i++)
|
||||||
|
{
|
||||||
|
if (Blobs[i]) delete[] Blobs[i];
|
||||||
|
Blobs[i] = nullptr;
|
||||||
|
BlobLens[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res)
|
||||||
|
{
|
||||||
|
ROMManager::CartType = 0;
|
||||||
|
//ROMManager::NDSSave = new SaveManager(savname);
|
||||||
|
|
||||||
|
//LoadCheats();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: load state!!!!
|
||||||
|
|
||||||
|
StartLocal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SyncMirrorClients()
|
||||||
|
{
|
||||||
|
SendBlobToMirrorClients(Blob_CartROM, NDSCart::CartROMSize, NDSCart::CartROM);
|
||||||
|
SendBlobToMirrorClients(Blob_CartSRAM, NDSCart::GetSaveMemoryLength(), NDSCart::GetSaveMemory());
|
||||||
|
|
||||||
|
// TODO: send initial state!!
|
||||||
|
|
||||||
|
u8 data[2];
|
||||||
|
data[0] = 0x04;
|
||||||
|
data[1] = (u8)Config::ConsoleType;
|
||||||
|
ENetPacket* pkt = enet_packet_create(&data, 2, ENET_PACKET_FLAG_RELIABLE);
|
||||||
|
enet_host_broadcast(MirrorHost, 1, pkt);
|
||||||
|
}
|
||||||
|
|
||||||
void StartGame()
|
void StartGame()
|
||||||
{
|
{
|
||||||
if (!IsHost)
|
if (!IsHost)
|
||||||
|
@ -454,13 +643,21 @@ void StartGame()
|
||||||
SpawnMirrorInstance(Players[i]);
|
SpawnMirrorInstance(Players[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncMirrorClients();
|
||||||
|
|
||||||
// tell remote peers to start game
|
// tell remote peers to start game
|
||||||
u8 cmd[1] = {0x04};
|
u8 cmd[1] = {0x04};
|
||||||
ENetPacket* pkt = enet_packet_create(cmd, sizeof(cmd), ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, sizeof(cmd), ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Host, 0, pkt);
|
enet_host_broadcast(Host, 0, pkt);
|
||||||
|
|
||||||
// tell other mirror instances to start the game
|
// tell other mirror instances to start the game
|
||||||
IPC::SendCommand(0xFFFF, IPC::Cmd_Start, 0, nullptr);
|
//IPC::SendCommand(0xFFFF, IPC::Cmd_Start, 0, nullptr);
|
||||||
|
|
||||||
|
// TO START MIRROR CLIENT SHITO
|
||||||
|
//
|
||||||
|
// 1. NDS::Reset()
|
||||||
|
// 2. load ROM
|
||||||
|
// 3. load state
|
||||||
|
|
||||||
// start game locally
|
// start game locally
|
||||||
StartLocal();
|
StartLocal();
|
||||||
|
@ -609,7 +806,7 @@ void ProcessClient()
|
||||||
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);
|
||||||
MirrorHost = enet_host_create(&mirroraddr, 16, 1, 0, 0);
|
MirrorHost = enet_host_create(&mirroraddr, 16, 2, 0, 0);
|
||||||
if (!MirrorHost)
|
if (!MirrorHost)
|
||||||
{
|
{
|
||||||
printf("mirror host shat itself :(\n");
|
printf("mirror host shat itself :(\n");
|
||||||
|
@ -650,9 +847,11 @@ printf("client mirror host connecting to %08X:%d\n", mirroraddr.host, mirroraddr
|
||||||
if (i != MyPlayer.ID)
|
if (i != MyPlayer.ID)
|
||||||
SpawnMirrorInstance(Players[i]);
|
SpawnMirrorInstance(Players[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SyncMirrorClients();
|
||||||
printf("bourf\n");
|
printf("bourf\n");
|
||||||
// tell other mirror instances to start the game
|
// tell other mirror instances to start the game
|
||||||
IPC::SendCommand(0xFFFF, IPC::Cmd_Start, 0, nullptr);
|
//IPC::SendCommand(0xFFFF, IPC::Cmd_Start, 0, nullptr);
|
||||||
printf("birf\n");
|
printf("birf\n");
|
||||||
// start game locally
|
// start game locally
|
||||||
StartLocal();
|
StartLocal();
|
||||||
|
@ -688,6 +887,7 @@ void ProcessMirrorHost()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
if (event.channelID == 0)
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != 4) break;
|
if (event.packet->dataLength != 4) break;
|
||||||
/*u8* data = (u8*)event.packet->data;
|
/*u8* data = (u8*)event.packet->data;
|
||||||
|
@ -771,6 +971,7 @@ void ProcessMirrorClient()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ENET_EVENT_TYPE_RECEIVE:
|
case ENET_EVENT_TYPE_RECEIVE:
|
||||||
|
if (event.channelID == 0)
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != sizeof(InputFrame)) break;
|
if (event.packet->dataLength != sizeof(InputFrame)) break;
|
||||||
|
|
||||||
|
@ -796,6 +997,10 @@ printf("mirror client lag notify: %d\n", lag);
|
||||||
enet_host_flush(MirrorHost);
|
enet_host_flush(MirrorHost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (event.channelID == 1)
|
||||||
|
{
|
||||||
|
RecvBlobFromMirrorHost(event.packet);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace ROMManager
|
||||||
{
|
{
|
||||||
|
|
||||||
extern QStringList FullROMPath;
|
extern QStringList FullROMPath;
|
||||||
|
extern int CartType;
|
||||||
|
|
||||||
extern SaveManager* NDSSave;
|
extern SaveManager* NDSSave;
|
||||||
extern SaveManager* GBASave;
|
extern SaveManager* GBASave;
|
||||||
|
|
Loading…
Reference in New Issue