begin work on state sync

This commit is contained in:
Arisotura 2023-04-05 21:11:55 +02:00
parent 586b2d4984
commit db09e0da9f
2 changed files with 213 additions and 7 deletions

View File

@ -27,11 +27,13 @@
#include <QProcess>
#include "NDS.h"
#include "NDSCart.h"
#include "main.h"
#include "IPC.h"
#include "Netplay.h"
#include "Input.h"
#include "ROMManager.h"
#include "Config.h"
#include "ui_NetplayStartHostDialog.h"
#include "ui_NetplayStartClientDialog.h"
@ -202,6 +204,21 @@ struct InputFrame
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()
{
@ -215,6 +232,14 @@ bool Init()
memset(Players, 0, sizeof(Players));
NumPlayers = 0;
for (int i = 0; i < Blob_MAX; i++)
{
Blobs[i] = nullptr;
BlobLens[i] = 0;
}
CurBlobType = -1;
CurBlobLen = 0;
if (enet_initialize() != 0)
{
printf("enet shat itself :(\n");
@ -329,7 +354,15 @@ void StartClient(const char* playername, const char* host, int port)
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)
{
printf("mirror shat itself :(\n");
@ -416,7 +449,7 @@ bool SpawnMirrorInstance(Player player)
if (newmask == curmask) continue;
newmask &= ~curmask;
for (int id = 0; id < 32; id++)
for (int id = 0; id < 16; id++)
{
if (newmask & (1 << id))
{
@ -431,8 +464,8 @@ bool SpawnMirrorInstance(Player player)
// setup that instance
printf("netplay: spawned mirror instance for player %d with ID %d, configuring\n", player.ID, newid);
std::string rompath = ROMManager::FullROMPath.join('|').toStdString();
IPC::SendCommandStr(1<<newid, IPC::Cmd_LoadROM, rompath);
//std::string rompath = ROMManager::FullROMPath.join('|').toStdString();
//IPC::SendCommandStr(1<<newid, IPC::Cmd_LoadROM, rompath);
if (player.Address == 0x0100007F) player.Address = HostAddress;
IPC::SendCommand(1<<newid, IPC::Cmd_SetupNetplayMirror, sizeof(Player), &player);
@ -440,6 +473,162 @@ bool SpawnMirrorInstance(Player player)
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()
{
if (!IsHost)
@ -454,13 +643,21 @@ void StartGame()
SpawnMirrorInstance(Players[i]);
}
SyncMirrorClients();
// tell remote peers to start game
u8 cmd[1] = {0x04};
ENetPacket* pkt = enet_packet_create(cmd, sizeof(cmd), ENET_PACKET_FLAG_RELIABLE);
enet_host_broadcast(Host, 0, pkt);
// 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
StartLocal();
@ -609,7 +806,7 @@ void ProcessClient()
mirroraddr.host = ENET_HOST_ANY;
mirroraddr.port = 8064+1 + data[1]; // FIXME!!!!
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)
{
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)
SpawnMirrorInstance(Players[i]);
}
SyncMirrorClients();
printf("bourf\n");
// 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");
// start game locally
StartLocal();
@ -688,6 +887,7 @@ void ProcessMirrorHost()
break;
case ENET_EVENT_TYPE_RECEIVE:
if (event.channelID == 0)
{
if (event.packet->dataLength != 4) break;
/*u8* data = (u8*)event.packet->data;
@ -771,6 +971,7 @@ void ProcessMirrorClient()
break;
case ENET_EVENT_TYPE_RECEIVE:
if (event.channelID == 0)
{
if (event.packet->dataLength != sizeof(InputFrame)) break;
@ -796,6 +997,10 @@ printf("mirror client lag notify: %d\n", lag);
enet_host_flush(MirrorHost);
}
}
else if (event.channelID == 1)
{
RecvBlobFromMirrorHost(event.packet);
}
break;
}

View File

@ -30,6 +30,7 @@ namespace ROMManager
{
extern QStringList FullROMPath;
extern int CartType;
extern SaveManager* NDSSave;
extern SaveManager* GBASave;