add warning when starting LAN game while having multiple instances open
also make the instance/window close code suck less (so that deleting an instance cleans up everything properly)
This commit is contained in:
parent
b50d2f377c
commit
d57fbd3f17
|
@ -64,7 +64,8 @@ MainWindow* topWindow = nullptr;
|
||||||
const string kWifiSettingsPath = "wfcsettings.bin";
|
const string kWifiSettingsPath = "wfcsettings.bin";
|
||||||
|
|
||||||
|
|
||||||
EmuInstance::EmuInstance(int inst) : instanceID(inst),
|
EmuInstance::EmuInstance(int inst) : deleting(false),
|
||||||
|
instanceID(inst),
|
||||||
globalCfg(Config::GetGlobalTable()),
|
globalCfg(Config::GetGlobalTable()),
|
||||||
localCfg(Config::GetLocalTable(inst))
|
localCfg(Config::GetLocalTable(inst))
|
||||||
{
|
{
|
||||||
|
@ -115,7 +116,8 @@ EmuInstance::EmuInstance(int inst) : instanceID(inst),
|
||||||
|
|
||||||
EmuInstance::~EmuInstance()
|
EmuInstance::~EmuInstance()
|
||||||
{
|
{
|
||||||
// TODO window cleanup and shit?
|
deleting = true;
|
||||||
|
deleteAllWindows();
|
||||||
|
|
||||||
LocalMP::End(instanceID);
|
LocalMP::End(instanceID);
|
||||||
|
|
||||||
|
@ -167,6 +169,44 @@ void EmuInstance::createWindow()
|
||||||
emuThread->attachWindow(win);
|
emuThread->attachWindow(win);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EmuInstance::deleteWindow(int id, bool close)
|
||||||
|
{
|
||||||
|
if (id >= kMaxWindows) return;
|
||||||
|
|
||||||
|
MainWindow* win = windowList[id];
|
||||||
|
if (!win) return;
|
||||||
|
|
||||||
|
if (win->hasOpenGL() && win == mainWindow)
|
||||||
|
{
|
||||||
|
// we intentionally don't unpause here
|
||||||
|
emuThread->emuPause();
|
||||||
|
emuThread->deinitContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
emuThread->detachWindow(win);
|
||||||
|
|
||||||
|
if (close)
|
||||||
|
win->close();
|
||||||
|
|
||||||
|
windowList[id] = nullptr;
|
||||||
|
numWindows--;
|
||||||
|
|
||||||
|
if (topWindow == win) topWindow = nullptr;
|
||||||
|
if (mainWindow == win) mainWindow = nullptr;
|
||||||
|
|
||||||
|
if ((!mainWindow) && !deleting)
|
||||||
|
{
|
||||||
|
// if we closed this instance's main window, delete the instance
|
||||||
|
deleteEmuInstance(instanceID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmuInstance::deleteAllWindows()
|
||||||
|
{
|
||||||
|
for (int i = kMaxWindows-1; i >= 0; i--)
|
||||||
|
deleteWindow(i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void EmuInstance::osdAddMessage(unsigned int color, const char* fmt, ...)
|
void EmuInstance::osdAddMessage(unsigned int color, const char* fmt, ...)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,8 @@ public:
|
||||||
std::string instanceFileSuffix();
|
std::string instanceFileSuffix();
|
||||||
|
|
||||||
void createWindow();
|
void createWindow();
|
||||||
|
void deleteWindow(int id, bool close);
|
||||||
|
void deleteAllWindows();
|
||||||
|
|
||||||
void osdAddMessage(unsigned int color, const char* fmt, ...);
|
void osdAddMessage(unsigned int color, const char* fmt, ...);
|
||||||
|
|
||||||
|
@ -215,6 +217,8 @@ private:
|
||||||
bool hotkeyPressed(int id) { return hotkeyPress & (1<<id); }
|
bool hotkeyPressed(int id) { return hotkeyPress & (1<<id); }
|
||||||
bool hotkeyReleased(int id) { return hotkeyRelease & (1<<id); }
|
bool hotkeyReleased(int id) { return hotkeyRelease & (1<<id); }
|
||||||
|
|
||||||
|
bool deleting;
|
||||||
|
|
||||||
int instanceID;
|
int instanceID;
|
||||||
|
|
||||||
EmuThread* emuThread;
|
EmuThread* emuThread;
|
||||||
|
|
|
@ -48,18 +48,7 @@
|
||||||
#include <enet/enet.h>
|
#include <enet/enet.h>
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QInputDialog>
|
|
||||||
#include <QMessageBox>
|
|
||||||
|
|
||||||
#include "LAN.h"
|
#include "LAN.h"
|
||||||
#include "Config.h"
|
|
||||||
#include "main.h"
|
|
||||||
|
|
||||||
#include "ui_LANStartHostDialog.h"
|
|
||||||
#include "ui_LANStartClientDialog.h"
|
|
||||||
#include "ui_LANDialog.h"
|
|
||||||
|
|
||||||
using namespace melonDS;
|
using namespace melonDS;
|
||||||
|
|
||||||
|
@ -72,6 +61,21 @@ const u32 kPacketMagic = 0x4946494E; // NIFI
|
||||||
|
|
||||||
const u32 kProtocolVersion = 1;
|
const u32 kProtocolVersion = 1;
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Chan_Cmd = 0, // channel 0 -- control commands
|
||||||
|
Chan_MP, // channel 1 -- MP data exchange
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Cmd_ClientInit = 1, // 01 -- host->client -- init new client and assign ID
|
||||||
|
Cmd_PlayerInfo, // 02 -- client->host -- send client player info to host
|
||||||
|
Cmd_PlayerList, // 03 -- host->client -- broadcast updated player list
|
||||||
|
Cmd_PlayerConnect, // 04 -- both -- signal connected state (ready to receive MP frames)
|
||||||
|
Cmd_PlayerDisconnect, // 05 -- both -- signal disconnected state (not receiving MP frames)
|
||||||
|
};
|
||||||
|
|
||||||
struct MPPacketHeader
|
struct MPPacketHeader
|
||||||
{
|
{
|
||||||
u32 Magic;
|
u32 Magic;
|
||||||
|
@ -250,7 +254,7 @@ bool StartHost(const char* playername, int numplayers)
|
||||||
memset(player, 0, sizeof(Player));
|
memset(player, 0, sizeof(Player));
|
||||||
player->ID = 0;
|
player->ID = 0;
|
||||||
strncpy(player->Name, playername, 31);
|
strncpy(player->Name, playername, 31);
|
||||||
player->Status = 2;
|
player->Status = Player_Host;
|
||||||
player->Address = 0x0100007F;
|
player->Address = 0x0100007F;
|
||||||
NumPlayers = 1;
|
NumPlayers = 1;
|
||||||
MaxPlayers = numplayers;
|
MaxPlayers = numplayers;
|
||||||
|
@ -293,7 +297,7 @@ bool StartClient(const char* playername, const char* host)
|
||||||
memset(player, 0, sizeof(Player));
|
memset(player, 0, sizeof(Player));
|
||||||
player->ID = 0;
|
player->ID = 0;
|
||||||
strncpy(player->Name, playername, 31);
|
strncpy(player->Name, playername, 31);
|
||||||
player->Status = 3;
|
player->Status = Player_Connecting;
|
||||||
|
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
int conn = 0;
|
int conn = 0;
|
||||||
|
@ -314,8 +318,8 @@ bool StartClient(const char* playername, const char* host)
|
||||||
else if (conn == 1 && event.type == ENET_EVENT_TYPE_RECEIVE)
|
else if (conn == 1 && event.type == ENET_EVENT_TYPE_RECEIVE)
|
||||||
{
|
{
|
||||||
u8* data = event.packet->data;
|
u8* data = event.packet->data;
|
||||||
if (event.channelID != 0) continue;
|
if (event.channelID != Chan_Cmd) continue;
|
||||||
if (data[0] != 0x01) continue;
|
if (data[0] != Cmd_ClientInit) continue;
|
||||||
if (event.packet->dataLength != 11) continue;
|
if (event.packet->dataLength != 11) continue;
|
||||||
|
|
||||||
u32 magic = data[1] | (data[2] << 8) | (data[3] << 16) | (data[4] << 24);
|
u32 magic = data[1] | (data[2] << 8) | (data[3] << 16) | (data[4] << 24);
|
||||||
|
@ -328,7 +332,7 @@ bool StartClient(const char* playername, const char* host)
|
||||||
// send player information
|
// send player information
|
||||||
MyPlayer.ID = data[9];
|
MyPlayer.ID = data[9];
|
||||||
u8 cmd[9+sizeof(Player)];
|
u8 cmd[9+sizeof(Player)];
|
||||||
cmd[0] = 0x02;
|
cmd[0] = Cmd_PlayerInfo;
|
||||||
cmd[1] = (u8)kLANMagic;
|
cmd[1] = (u8)kLANMagic;
|
||||||
cmd[2] = (u8)(kLANMagic >> 8);
|
cmd[2] = (u8)(kLANMagic >> 8);
|
||||||
cmd[3] = (u8)(kLANMagic >> 16);
|
cmd[3] = (u8)(kLANMagic >> 16);
|
||||||
|
@ -339,7 +343,7 @@ bool StartClient(const char* playername, const char* host)
|
||||||
cmd[8] = (u8)(kProtocolVersion >> 24);
|
cmd[8] = (u8)(kProtocolVersion >> 24);
|
||||||
memcpy(&cmd[9], &MyPlayer, sizeof(Player));
|
memcpy(&cmd[9], &MyPlayer, sizeof(Player));
|
||||||
ENetPacket* pkt = enet_packet_create(cmd, 9+sizeof(Player), ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, 9+sizeof(Player), ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_peer_send(event.peer, 0, pkt);
|
enet_peer_send(event.peer, Chan_Cmd, pkt);
|
||||||
|
|
||||||
conn = 2;
|
conn = 2;
|
||||||
break;
|
break;
|
||||||
|
@ -475,11 +479,11 @@ void ProcessDiscovery()
|
||||||
void HostUpdatePlayerList()
|
void HostUpdatePlayerList()
|
||||||
{
|
{
|
||||||
u8 cmd[2+sizeof(Players)];
|
u8 cmd[2+sizeof(Players)];
|
||||||
cmd[0] = 0x03;
|
cmd[0] = Cmd_PlayerList;
|
||||||
cmd[1] = (u8)NumPlayers;
|
cmd[1] = (u8)NumPlayers;
|
||||||
memcpy(&cmd[2], Players, sizeof(Players));
|
memcpy(&cmd[2], Players, sizeof(Players));
|
||||||
ENetPacket* pkt = enet_packet_create(cmd, 2+sizeof(Players), ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, 2+sizeof(Players), ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Host, 0, pkt);
|
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
||||||
|
|
||||||
//if (lanDlg)
|
//if (lanDlg)
|
||||||
// lanDlg->updatePlayerList();
|
// lanDlg->updatePlayerList();
|
||||||
|
@ -510,13 +514,13 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
for (id = 0; id < 16; id++)
|
for (id = 0; id < 16; id++)
|
||||||
{
|
{
|
||||||
if (id >= NumPlayers) break;
|
if (id >= NumPlayers) break;
|
||||||
if (Players[id].Status == 0) break;
|
if (Players[id].Status == Player_None) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (id < 16)
|
if (id < 16)
|
||||||
{
|
{
|
||||||
u8 cmd[11];
|
u8 cmd[11];
|
||||||
cmd[0] = 0x01;
|
cmd[0] = Cmd_ClientInit;
|
||||||
cmd[1] = (u8)kLANMagic;
|
cmd[1] = (u8)kLANMagic;
|
||||||
cmd[2] = (u8)(kLANMagic >> 8);
|
cmd[2] = (u8)(kLANMagic >> 8);
|
||||||
cmd[3] = (u8)(kLANMagic >> 16);
|
cmd[3] = (u8)(kLANMagic >> 16);
|
||||||
|
@ -528,10 +532,10 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
cmd[9] = (u8)id;
|
cmd[9] = (u8)id;
|
||||||
cmd[10] = MaxPlayers;
|
cmd[10] = MaxPlayers;
|
||||||
ENetPacket* pkt = enet_packet_create(cmd, 11, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(cmd, 11, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_peer_send(event.peer, 0, pkt);
|
enet_peer_send(event.peer, Chan_Cmd, pkt);
|
||||||
|
|
||||||
Players[id].ID = id;
|
Players[id].ID = id;
|
||||||
Players[id].Status = 3;
|
Players[id].Status = Player_Connecting;
|
||||||
Players[id].Address = event.peer->address.host;
|
Players[id].Address = event.peer->address.host;
|
||||||
event.peer->data = &Players[id];
|
event.peer->data = &Players[id];
|
||||||
NumPlayers++;
|
NumPlayers++;
|
||||||
|
@ -557,7 +561,7 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
RemotePeers[id] = nullptr;
|
RemotePeers[id] = nullptr;
|
||||||
|
|
||||||
player->ID = 0;
|
player->ID = 0;
|
||||||
player->Status = 0;
|
player->Status = Player_None;
|
||||||
NumPlayers--;
|
NumPlayers--;
|
||||||
|
|
||||||
// broadcast updated player list
|
// broadcast updated player list
|
||||||
|
@ -572,7 +576,7 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
u8* data = (u8*)event.packet->data;
|
u8* data = (u8*)event.packet->data;
|
||||||
switch (data[0])
|
switch (data[0])
|
||||||
{
|
{
|
||||||
case 0x02: // client sending player info
|
case Cmd_PlayerInfo: // client sending player info
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != (9+sizeof(Player))) break;
|
if (event.packet->dataLength != (9+sizeof(Player))) break;
|
||||||
|
|
||||||
|
@ -595,7 +599,7 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
player.Status = 1;
|
player.Status = Player_Client;
|
||||||
player.Address = event.peer->address.host;
|
player.Address = event.peer->address.host;
|
||||||
memcpy(hostside, &player, sizeof(Player));
|
memcpy(hostside, &player, sizeof(Player));
|
||||||
|
|
||||||
|
@ -604,7 +608,7 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: // player connected
|
case Cmd_PlayerConnect: // player connected
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
|
@ -615,7 +619,7 @@ void ProcessHostEvent(ENetEvent& event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: // player disconnected
|
case Cmd_PlayerDisconnect: // player disconnected
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
|
@ -646,7 +650,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
{
|
{
|
||||||
Player* player = &Players[i];
|
Player* player = &Players[i];
|
||||||
if (i == MyPlayer.ID) continue;
|
if (i == MyPlayer.ID) continue;
|
||||||
if (player->Status != 1) continue;
|
if (player->Status != Player_Client) continue;
|
||||||
|
|
||||||
if (player->Address == event.peer->address.host)
|
if (player->Address == event.peer->address.host)
|
||||||
{
|
{
|
||||||
|
@ -676,7 +680,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
int id = player->ID;
|
int id = player->ID;
|
||||||
RemotePeers[id] = nullptr;
|
RemotePeers[id] = nullptr;
|
||||||
|
|
||||||
player->Status = 4;
|
player->Status = Player_Disconnected;
|
||||||
|
|
||||||
ClientUpdatePlayerList();
|
ClientUpdatePlayerList();
|
||||||
}
|
}
|
||||||
|
@ -689,7 +693,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
u8* data = (u8*)event.packet->data;
|
u8* data = (u8*)event.packet->data;
|
||||||
switch (data[0])
|
switch (data[0])
|
||||||
{
|
{
|
||||||
case 0x03: // host sending player list
|
case Cmd_PlayerList: // host sending player list
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != (2+sizeof(Players))) break;
|
if (event.packet->dataLength != (2+sizeof(Players))) break;
|
||||||
if (data[1] > 16) break;
|
if (data[1] > 16) break;
|
||||||
|
@ -709,7 +713,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
{
|
{
|
||||||
Player* player = &Players[i];
|
Player* player = &Players[i];
|
||||||
if (i == MyPlayer.ID) continue;
|
if (i == MyPlayer.ID) continue;
|
||||||
if (player->Status != 1) continue;
|
if (player->Status != Player_Client) continue;
|
||||||
|
|
||||||
if (!RemotePeers[i])
|
if (!RemotePeers[i])
|
||||||
{
|
{
|
||||||
|
@ -727,7 +731,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x04: // player connected
|
case Cmd_PlayerConnect: // player connected
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
|
@ -738,7 +742,7 @@ void ProcessClientEvent(ENetEvent& event)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x05: // player disconnected
|
case Cmd_PlayerDisconnect: // player disconnected
|
||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
|
@ -813,7 +817,7 @@ void Process(int type)
|
||||||
ENetEvent event;
|
ENetEvent event;
|
||||||
while (enet_host_service(Host, &event, timeout) > 0)
|
while (enet_host_service(Host, &event, timeout) > 0)
|
||||||
{
|
{
|
||||||
if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == 1)
|
if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == Chan_MP)
|
||||||
{
|
{
|
||||||
MPPacketHeader* header = (MPPacketHeader*)&event.packet->data[0];
|
MPPacketHeader* header = (MPPacketHeader*)&event.packet->data[0];
|
||||||
//printf("- enet_host_service: (%d) got MP frame, len=%d type=%08X fc=%04X\n", type, event.packet->dataLength, header->Type, *(u16*)&event.packet->data[sizeof(MPPacketHeader)+12]);
|
//printf("- enet_host_service: (%d) got MP frame, len=%d type=%08X fc=%04X\n", type, event.packet->dataLength, header->Type, *(u16*)&event.packet->data[sizeof(MPPacketHeader)+12]);
|
||||||
|
@ -871,7 +875,7 @@ void ProcessFrame()
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
for (int i = 0; i < 16; i++)
|
||||||
{
|
{
|
||||||
if (Players[i].Status == 0) continue;
|
if (Players[i].Status == Player_None) continue;
|
||||||
if (i == MyPlayer.ID) continue;
|
if (i == MyPlayer.ID) continue;
|
||||||
if (!RemotePeers[i]) continue;
|
if (!RemotePeers[i]) continue;
|
||||||
|
|
||||||
|
@ -897,9 +901,9 @@ void MPBegin()
|
||||||
LastHostID = -1;
|
LastHostID = -1;
|
||||||
LastHostPeer = nullptr;
|
LastHostPeer = nullptr;
|
||||||
|
|
||||||
u8 cmd = 0x04;
|
u8 cmd = Cmd_PlayerConnect;
|
||||||
ENetPacket* pkt = enet_packet_create(&cmd, 1, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(&cmd, 1, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Host, 0, pkt);
|
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPEnd()
|
void MPEnd()
|
||||||
|
@ -908,9 +912,9 @@ void MPEnd()
|
||||||
|
|
||||||
ConnectedBitmask &= ~(1 << MyPlayer.ID);
|
ConnectedBitmask &= ~(1 << MyPlayer.ID);
|
||||||
|
|
||||||
u8 cmd = 0x05;
|
u8 cmd = Cmd_PlayerDisconnect;
|
||||||
ENetPacket* pkt = enet_packet_create(&cmd, 1, ENET_PACKET_FLAG_RELIABLE);
|
ENetPacket* pkt = enet_packet_create(&cmd, 1, ENET_PACKET_FLAG_RELIABLE);
|
||||||
enet_host_broadcast(Host, 0, pkt);
|
enet_host_broadcast(Host, Chan_Cmd, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -935,9 +939,9 @@ int SendMPPacketGeneric(u32 type, u8* packet, int len, u64 timestamp)
|
||||||
memcpy(&enetpacket->data[sizeof(MPPacketHeader)], packet, len);
|
memcpy(&enetpacket->data[sizeof(MPPacketHeader)], packet, len);
|
||||||
|
|
||||||
if (((type & 0xFFFF) == 2) && LastHostPeer)
|
if (((type & 0xFFFF) == 2) && LastHostPeer)
|
||||||
enet_peer_send(LastHostPeer, 1, enetpacket);
|
enet_peer_send(LastHostPeer, Chan_MP, enetpacket);
|
||||||
else
|
else
|
||||||
enet_host_broadcast(Host, 1, enetpacket);
|
enet_host_broadcast(Host, Chan_MP, enetpacket);
|
||||||
enet_host_flush(Host);
|
enet_host_flush(Host);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
|
@ -27,39 +27,49 @@
|
||||||
|
|
||||||
namespace LAN
|
namespace LAN
|
||||||
{
|
{
|
||||||
|
using namespace melonDS;
|
||||||
|
|
||||||
|
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
|
struct Player
|
||||||
{
|
{
|
||||||
int ID;
|
int ID;
|
||||||
char Name[32];
|
char Name[32];
|
||||||
int Status; // 0=no player 1=normal 2=host 3=connecting 4=disconnected
|
PlayerStatus Status;
|
||||||
melonDS::u32 Address;
|
u32 Address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DiscoveryData
|
struct DiscoveryData
|
||||||
{
|
{
|
||||||
melonDS::u32 Magic;
|
u32 Magic;
|
||||||
melonDS::u32 Version;
|
u32 Version;
|
||||||
melonDS::u32 Tick;
|
u32 Tick;
|
||||||
char SessionName[64];
|
char SessionName[64];
|
||||||
melonDS::u8 NumPlayers;
|
u8 NumPlayers;
|
||||||
melonDS::u8 MaxPlayers;
|
u8 MaxPlayers;
|
||||||
melonDS::u8 Status; // 0=idle 1=playing
|
u8 Status; // 0=idle 1=playing
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
extern bool Active;
|
extern bool Active;
|
||||||
|
|
||||||
extern std::map<melonDS::u32, DiscoveryData> DiscoveryList;
|
extern std::map<u32, DiscoveryData> DiscoveryList;
|
||||||
extern QMutex DiscoveryMutex; // TODO: turn into Platform::Mutex or rework this to be nicer
|
extern QMutex DiscoveryMutex; // TODO: turn into Platform::Mutex or rework this to be nicer
|
||||||
|
|
||||||
extern Player Players[16];
|
extern Player Players[16];
|
||||||
extern melonDS::u32 PlayerPing[16];
|
extern u32 PlayerPing[16];
|
||||||
extern int NumPlayers;
|
extern int NumPlayers;
|
||||||
extern int MaxPlayers;
|
extern int MaxPlayers;
|
||||||
|
|
||||||
extern Player MyPlayer;
|
extern Player MyPlayer;
|
||||||
extern melonDS::u32 HostAddress;
|
extern u32 HostAddress;
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
void DeInit();
|
void DeInit();
|
||||||
|
@ -75,13 +85,13 @@ void SetMPRecvTimeout(int timeout);
|
||||||
void MPBegin();
|
void MPBegin();
|
||||||
void MPEnd();
|
void MPEnd();
|
||||||
|
|
||||||
int SendMPPacket(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
int SendMPPacket(u8* data, int len, u64 timestamp);
|
||||||
int RecvMPPacket(melonDS::u8* data, melonDS::u64* timestamp);
|
int RecvMPPacket(u8* data, u64* timestamp);
|
||||||
int SendMPCmd(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
int SendMPCmd(u8* data, int len, u64 timestamp);
|
||||||
int SendMPReply(melonDS::u8* data, int len, melonDS::u64 timestamp, melonDS::u16 aid);
|
int SendMPReply(u8* data, int len, u64 timestamp, u16 aid);
|
||||||
int SendMPAck(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
int SendMPAck(u8* data, int len, u64 timestamp);
|
||||||
int RecvMPHostPacket(melonDS::u8* data, melonDS::u64* timestamp);
|
int RecvMPHostPacket(u8* data, u64* timestamp);
|
||||||
melonDS::u16 RecvMPReplies(melonDS::u8* data, melonDS::u64 timestamp, melonDS::u16 aidmask);
|
u16 RecvMPReplies(u8* data, u64 timestamp, u16 aidmask);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,6 +73,7 @@
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "Savestate.h"
|
#include "Savestate.h"
|
||||||
#include "LocalMP.h"
|
#include "LocalMP.h"
|
||||||
|
#include "LANDialog.h"
|
||||||
|
|
||||||
//#include "main_shaders.h"
|
//#include "main_shaders.h"
|
||||||
|
|
||||||
|
@ -763,24 +764,9 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||||
QByteArray geom = saveGeometry();
|
QByteArray geom = saveGeometry();
|
||||||
QByteArray enc = geom.toBase64(QByteArray::Base64Encoding);
|
QByteArray enc = geom.toBase64(QByteArray::Base64Encoding);
|
||||||
windowCfg.SetString("Geometry", enc.toStdString());
|
windowCfg.SetString("Geometry", enc.toStdString());
|
||||||
|
|
||||||
Config::Save();
|
Config::Save();
|
||||||
|
|
||||||
if (hasOGL && (windowID == 0))
|
emuInstance->deleteWindow(windowID, false);
|
||||||
{
|
|
||||||
// we intentionally don't unpause here
|
|
||||||
emuThread->emuPause();
|
|
||||||
emuThread->deinitContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
emuThread->detachWindow(this);
|
|
||||||
|
|
||||||
if (windowID == 0)
|
|
||||||
{
|
|
||||||
int inst = emuInstance->instanceID;
|
|
||||||
deleteEmuInstance(inst);
|
|
||||||
}
|
|
||||||
|
|
||||||
QMainWindow::closeEvent(event);
|
QMainWindow::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1694,12 +1680,14 @@ void MainWindow::onMPNewInstance()
|
||||||
|
|
||||||
void MainWindow::onLANStartHost()
|
void MainWindow::onLANStartHost()
|
||||||
{
|
{
|
||||||
//LANStartHostDialog::openDlg(this);
|
if (!lanWarning(true)) return;
|
||||||
|
LANStartHostDialog::openDlg(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onLANStartClient()
|
void MainWindow::onLANStartClient()
|
||||||
{
|
{
|
||||||
//LANStartClientDialog::openDlg(this);
|
if (!lanWarning(false)) return;
|
||||||
|
LANStartClientDialog::openDlg(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onNPStartHost()
|
void MainWindow::onNPStartHost()
|
||||||
|
@ -1720,6 +1708,24 @@ void MainWindow::onNPTest()
|
||||||
//Netplay::StartGame();
|
//Netplay::StartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MainWindow::lanWarning(bool host)
|
||||||
|
{
|
||||||
|
if (numEmuInstances() < 2)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QString verb = host ? "host" : "join";
|
||||||
|
QString msg = "Multiple emulator instances are currently open.\n"
|
||||||
|
"If you "+verb+" a LAN game now, all secondary instances will be closed.\n\n"
|
||||||
|
"Do you wish to continue?";
|
||||||
|
|
||||||
|
auto res = QMessageBox::warning(this, "melonDS", msg, QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
|
||||||
|
if (res == QMessageBox::No)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
deleteAllEmuInstances(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onOpenEmuSettings()
|
void MainWindow::onOpenEmuSettings()
|
||||||
{
|
{
|
||||||
emuThread->emuPause();
|
emuThread->emuPause();
|
||||||
|
|
|
@ -237,6 +237,8 @@ private:
|
||||||
|
|
||||||
void createScreenPanel();
|
void createScreenPanel();
|
||||||
|
|
||||||
|
bool lanWarning(bool host);
|
||||||
|
|
||||||
bool showOSD;
|
bool showOSD;
|
||||||
|
|
||||||
bool hasOGL;
|
bool hasOGL;
|
||||||
|
|
|
@ -124,12 +124,25 @@ void deleteEmuInstance(int id)
|
||||||
emuInstances[id] = nullptr;
|
emuInstances[id] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void deleteAllEmuInstances()
|
void deleteAllEmuInstances(int first)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < kMaxEmuInstances; i++)
|
for (int i = first; i < kMaxEmuInstances; i++)
|
||||||
deleteEmuInstance(i);
|
deleteEmuInstance(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int numEmuInstances()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < kMaxEmuInstances; i++)
|
||||||
|
{
|
||||||
|
if (emuInstances[i])
|
||||||
|
ret++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void pathInit()
|
void pathInit()
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,6 +50,7 @@ extern QString emuDirectory;
|
||||||
|
|
||||||
bool createEmuInstance();
|
bool createEmuInstance();
|
||||||
void deleteEmuInstance(int id);
|
void deleteEmuInstance(int id);
|
||||||
void deleteAllEmuInstances();
|
void deleteAllEmuInstances(int first = 0);
|
||||||
|
int numEmuInstances();
|
||||||
|
|
||||||
#endif // MAIN_H
|
#endif // MAIN_H
|
||||||
|
|
Loading…
Reference in New Issue