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";
|
||||
|
||||
|
||||
EmuInstance::EmuInstance(int inst) : instanceID(inst),
|
||||
EmuInstance::EmuInstance(int inst) : deleting(false),
|
||||
instanceID(inst),
|
||||
globalCfg(Config::GetGlobalTable()),
|
||||
localCfg(Config::GetLocalTable(inst))
|
||||
{
|
||||
|
@ -115,7 +116,8 @@ EmuInstance::EmuInstance(int inst) : instanceID(inst),
|
|||
|
||||
EmuInstance::~EmuInstance()
|
||||
{
|
||||
// TODO window cleanup and shit?
|
||||
deleting = true;
|
||||
deleteAllWindows();
|
||||
|
||||
LocalMP::End(instanceID);
|
||||
|
||||
|
@ -167,6 +169,44 @@ void EmuInstance::createWindow()
|
|||
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, ...)
|
||||
{
|
||||
|
|
|
@ -91,6 +91,8 @@ public:
|
|||
std::string instanceFileSuffix();
|
||||
|
||||
void createWindow();
|
||||
void deleteWindow(int id, bool close);
|
||||
void deleteAllWindows();
|
||||
|
||||
void osdAddMessage(unsigned int color, const char* fmt, ...);
|
||||
|
||||
|
@ -215,6 +217,8 @@ private:
|
|||
bool hotkeyPressed(int id) { return hotkeyPress & (1<<id); }
|
||||
bool hotkeyReleased(int id) { return hotkeyRelease & (1<<id); }
|
||||
|
||||
bool deleting;
|
||||
|
||||
int instanceID;
|
||||
|
||||
EmuThread* emuThread;
|
||||
|
|
|
@ -48,18 +48,7 @@
|
|||
#include <enet/enet.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QPushButton>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
#include "LAN.h"
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
|
||||
#include "ui_LANStartHostDialog.h"
|
||||
#include "ui_LANStartClientDialog.h"
|
||||
#include "ui_LANDialog.h"
|
||||
|
||||
using namespace melonDS;
|
||||
|
||||
|
@ -72,6 +61,21 @@ const u32 kPacketMagic = 0x4946494E; // NIFI
|
|||
|
||||
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
|
||||
{
|
||||
u32 Magic;
|
||||
|
@ -250,7 +254,7 @@ bool StartHost(const char* playername, int numplayers)
|
|||
memset(player, 0, sizeof(Player));
|
||||
player->ID = 0;
|
||||
strncpy(player->Name, playername, 31);
|
||||
player->Status = 2;
|
||||
player->Status = Player_Host;
|
||||
player->Address = 0x0100007F;
|
||||
NumPlayers = 1;
|
||||
MaxPlayers = numplayers;
|
||||
|
@ -293,7 +297,7 @@ bool StartClient(const char* playername, const char* host)
|
|||
memset(player, 0, sizeof(Player));
|
||||
player->ID = 0;
|
||||
strncpy(player->Name, playername, 31);
|
||||
player->Status = 3;
|
||||
player->Status = Player_Connecting;
|
||||
|
||||
ENetEvent event;
|
||||
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)
|
||||
{
|
||||
u8* data = event.packet->data;
|
||||
if (event.channelID != 0) continue;
|
||||
if (data[0] != 0x01) continue;
|
||||
if (event.channelID != Chan_Cmd) continue;
|
||||
if (data[0] != Cmd_ClientInit) continue;
|
||||
if (event.packet->dataLength != 11) continue;
|
||||
|
||||
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
|
||||
MyPlayer.ID = data[9];
|
||||
u8 cmd[9+sizeof(Player)];
|
||||
cmd[0] = 0x02;
|
||||
cmd[0] = Cmd_PlayerInfo;
|
||||
cmd[1] = (u8)kLANMagic;
|
||||
cmd[2] = (u8)(kLANMagic >> 8);
|
||||
cmd[3] = (u8)(kLANMagic >> 16);
|
||||
|
@ -339,7 +343,7 @@ bool StartClient(const char* playername, const char* host)
|
|||
cmd[8] = (u8)(kProtocolVersion >> 24);
|
||||
memcpy(&cmd[9], &MyPlayer, sizeof(Player));
|
||||
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;
|
||||
break;
|
||||
|
@ -475,11 +479,11 @@ void ProcessDiscovery()
|
|||
void HostUpdatePlayerList()
|
||||
{
|
||||
u8 cmd[2+sizeof(Players)];
|
||||
cmd[0] = 0x03;
|
||||
cmd[0] = Cmd_PlayerList;
|
||||
cmd[1] = (u8)NumPlayers;
|
||||
memcpy(&cmd[2], Players, sizeof(Players));
|
||||
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)
|
||||
// lanDlg->updatePlayerList();
|
||||
|
@ -510,13 +514,13 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
for (id = 0; id < 16; id++)
|
||||
{
|
||||
if (id >= NumPlayers) break;
|
||||
if (Players[id].Status == 0) break;
|
||||
if (Players[id].Status == Player_None) break;
|
||||
}
|
||||
|
||||
if (id < 16)
|
||||
{
|
||||
u8 cmd[11];
|
||||
cmd[0] = 0x01;
|
||||
cmd[0] = Cmd_ClientInit;
|
||||
cmd[1] = (u8)kLANMagic;
|
||||
cmd[2] = (u8)(kLANMagic >> 8);
|
||||
cmd[3] = (u8)(kLANMagic >> 16);
|
||||
|
@ -528,10 +532,10 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
cmd[9] = (u8)id;
|
||||
cmd[10] = MaxPlayers;
|
||||
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].Status = 3;
|
||||
Players[id].Status = Player_Connecting;
|
||||
Players[id].Address = event.peer->address.host;
|
||||
event.peer->data = &Players[id];
|
||||
NumPlayers++;
|
||||
|
@ -557,7 +561,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
RemotePeers[id] = nullptr;
|
||||
|
||||
player->ID = 0;
|
||||
player->Status = 0;
|
||||
player->Status = Player_None;
|
||||
NumPlayers--;
|
||||
|
||||
// broadcast updated player list
|
||||
|
@ -572,7 +576,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
u8* data = (u8*)event.packet->data;
|
||||
switch (data[0])
|
||||
{
|
||||
case 0x02: // client sending player info
|
||||
case Cmd_PlayerInfo: // client sending player info
|
||||
{
|
||||
if (event.packet->dataLength != (9+sizeof(Player))) break;
|
||||
|
||||
|
@ -595,7 +599,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
break;
|
||||
}
|
||||
|
||||
player.Status = 1;
|
||||
player.Status = Player_Client;
|
||||
player.Address = event.peer->address.host;
|
||||
memcpy(hostside, &player, sizeof(Player));
|
||||
|
||||
|
@ -604,7 +608,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x04: // player connected
|
||||
case Cmd_PlayerConnect: // player connected
|
||||
{
|
||||
if (event.packet->dataLength != 1) break;
|
||||
Player* player = (Player*)event.peer->data;
|
||||
|
@ -615,7 +619,7 @@ void ProcessHostEvent(ENetEvent& event)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x05: // player disconnected
|
||||
case Cmd_PlayerDisconnect: // player disconnected
|
||||
{
|
||||
if (event.packet->dataLength != 1) break;
|
||||
Player* player = (Player*)event.peer->data;
|
||||
|
@ -646,7 +650,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
{
|
||||
Player* player = &Players[i];
|
||||
if (i == MyPlayer.ID) continue;
|
||||
if (player->Status != 1) continue;
|
||||
if (player->Status != Player_Client) continue;
|
||||
|
||||
if (player->Address == event.peer->address.host)
|
||||
{
|
||||
|
@ -676,7 +680,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
int id = player->ID;
|
||||
RemotePeers[id] = nullptr;
|
||||
|
||||
player->Status = 4;
|
||||
player->Status = Player_Disconnected;
|
||||
|
||||
ClientUpdatePlayerList();
|
||||
}
|
||||
|
@ -689,7 +693,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
u8* data = (u8*)event.packet->data;
|
||||
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 (data[1] > 16) break;
|
||||
|
@ -709,7 +713,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
{
|
||||
Player* player = &Players[i];
|
||||
if (i == MyPlayer.ID) continue;
|
||||
if (player->Status != 1) continue;
|
||||
if (player->Status != Player_Client) continue;
|
||||
|
||||
if (!RemotePeers[i])
|
||||
{
|
||||
|
@ -727,7 +731,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x04: // player connected
|
||||
case Cmd_PlayerConnect: // player connected
|
||||
{
|
||||
if (event.packet->dataLength != 1) break;
|
||||
Player* player = (Player*)event.peer->data;
|
||||
|
@ -738,7 +742,7 @@ void ProcessClientEvent(ENetEvent& event)
|
|||
}
|
||||
break;
|
||||
|
||||
case 0x05: // player disconnected
|
||||
case Cmd_PlayerDisconnect: // player disconnected
|
||||
{
|
||||
if (event.packet->dataLength != 1) break;
|
||||
Player* player = (Player*)event.peer->data;
|
||||
|
@ -813,7 +817,7 @@ void Process(int type)
|
|||
ENetEvent event;
|
||||
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];
|
||||
//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++)
|
||||
{
|
||||
if (Players[i].Status == 0) continue;
|
||||
if (Players[i].Status == Player_None) continue;
|
||||
if (i == MyPlayer.ID) continue;
|
||||
if (!RemotePeers[i]) continue;
|
||||
|
||||
|
@ -897,9 +901,9 @@ void MPBegin()
|
|||
LastHostID = -1;
|
||||
LastHostPeer = nullptr;
|
||||
|
||||
u8 cmd = 0x04;
|
||||
u8 cmd = Cmd_PlayerConnect;
|
||||
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()
|
||||
|
@ -908,9 +912,9 @@ void MPEnd()
|
|||
|
||||
ConnectedBitmask &= ~(1 << MyPlayer.ID);
|
||||
|
||||
u8 cmd = 0x05;
|
||||
u8 cmd = Cmd_PlayerDisconnect;
|
||||
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);
|
||||
|
||||
if (((type & 0xFFFF) == 2) && LastHostPeer)
|
||||
enet_peer_send(LastHostPeer, 1, enetpacket);
|
||||
enet_peer_send(LastHostPeer, Chan_MP, enetpacket);
|
||||
else
|
||||
enet_host_broadcast(Host, 1, enetpacket);
|
||||
enet_host_broadcast(Host, Chan_MP, enetpacket);
|
||||
enet_host_flush(Host);
|
||||
|
||||
return len;
|
||||
|
|
|
@ -27,39 +27,49 @@
|
|||
|
||||
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
|
||||
{
|
||||
int ID;
|
||||
char Name[32];
|
||||
int Status; // 0=no player 1=normal 2=host 3=connecting 4=disconnected
|
||||
melonDS::u32 Address;
|
||||
PlayerStatus Status;
|
||||
u32 Address;
|
||||
};
|
||||
|
||||
struct DiscoveryData
|
||||
{
|
||||
melonDS::u32 Magic;
|
||||
melonDS::u32 Version;
|
||||
melonDS::u32 Tick;
|
||||
u32 Magic;
|
||||
u32 Version;
|
||||
u32 Tick;
|
||||
char SessionName[64];
|
||||
melonDS::u8 NumPlayers;
|
||||
melonDS::u8 MaxPlayers;
|
||||
melonDS::u8 Status; // 0=idle 1=playing
|
||||
u8 NumPlayers;
|
||||
u8 MaxPlayers;
|
||||
u8 Status; // 0=idle 1=playing
|
||||
};
|
||||
|
||||
|
||||
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 Player Players[16];
|
||||
extern melonDS::u32 PlayerPing[16];
|
||||
extern u32 PlayerPing[16];
|
||||
extern int NumPlayers;
|
||||
extern int MaxPlayers;
|
||||
|
||||
extern Player MyPlayer;
|
||||
extern melonDS::u32 HostAddress;
|
||||
extern u32 HostAddress;
|
||||
|
||||
bool Init();
|
||||
void DeInit();
|
||||
|
@ -75,13 +85,13 @@ void SetMPRecvTimeout(int timeout);
|
|||
void MPBegin();
|
||||
void MPEnd();
|
||||
|
||||
int SendMPPacket(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
||||
int RecvMPPacket(melonDS::u8* data, melonDS::u64* timestamp);
|
||||
int SendMPCmd(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
||||
int SendMPReply(melonDS::u8* data, int len, melonDS::u64 timestamp, melonDS::u16 aid);
|
||||
int SendMPAck(melonDS::u8* data, int len, melonDS::u64 timestamp);
|
||||
int RecvMPHostPacket(melonDS::u8* data, melonDS::u64* timestamp);
|
||||
melonDS::u16 RecvMPReplies(melonDS::u8* data, melonDS::u64 timestamp, melonDS::u16 aidmask);
|
||||
int SendMPPacket(u8* data, int len, u64 timestamp);
|
||||
int RecvMPPacket(u8* data, u64* timestamp);
|
||||
int SendMPCmd(u8* data, int len, u64 timestamp);
|
||||
int SendMPReply(u8* data, int len, u64 timestamp, u16 aid);
|
||||
int SendMPAck(u8* data, int len, u64 timestamp);
|
||||
int RecvMPHostPacket(u8* data, u64* timestamp);
|
||||
u16 RecvMPReplies(u8* data, u64 timestamp, u16 aidmask);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "version.h"
|
||||
#include "Savestate.h"
|
||||
#include "LocalMP.h"
|
||||
#include "LANDialog.h"
|
||||
|
||||
//#include "main_shaders.h"
|
||||
|
||||
|
@ -763,24 +764,9 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
|||
QByteArray geom = saveGeometry();
|
||||
QByteArray enc = geom.toBase64(QByteArray::Base64Encoding);
|
||||
windowCfg.SetString("Geometry", enc.toStdString());
|
||||
|
||||
Config::Save();
|
||||
|
||||
if (hasOGL && (windowID == 0))
|
||||
{
|
||||
// we intentionally don't unpause here
|
||||
emuThread->emuPause();
|
||||
emuThread->deinitContext();
|
||||
}
|
||||
|
||||
emuThread->detachWindow(this);
|
||||
|
||||
if (windowID == 0)
|
||||
{
|
||||
int inst = emuInstance->instanceID;
|
||||
deleteEmuInstance(inst);
|
||||
}
|
||||
|
||||
emuInstance->deleteWindow(windowID, false);
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
|
@ -1694,12 +1680,14 @@ void MainWindow::onMPNewInstance()
|
|||
|
||||
void MainWindow::onLANStartHost()
|
||||
{
|
||||
//LANStartHostDialog::openDlg(this);
|
||||
if (!lanWarning(true)) return;
|
||||
LANStartHostDialog::openDlg(this);
|
||||
}
|
||||
|
||||
void MainWindow::onLANStartClient()
|
||||
{
|
||||
//LANStartClientDialog::openDlg(this);
|
||||
if (!lanWarning(false)) return;
|
||||
LANStartClientDialog::openDlg(this);
|
||||
}
|
||||
|
||||
void MainWindow::onNPStartHost()
|
||||
|
@ -1720,6 +1708,24 @@ void MainWindow::onNPTest()
|
|||
//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()
|
||||
{
|
||||
emuThread->emuPause();
|
||||
|
|
|
@ -237,6 +237,8 @@ private:
|
|||
|
||||
void createScreenPanel();
|
||||
|
||||
bool lanWarning(bool host);
|
||||
|
||||
bool showOSD;
|
||||
|
||||
bool hasOGL;
|
||||
|
|
|
@ -124,12 +124,25 @@ void deleteEmuInstance(int id)
|
|||
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);
|
||||
}
|
||||
|
||||
int numEmuInstances()
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
for (int i = 0; i < kMaxEmuInstances; i++)
|
||||
{
|
||||
if (emuInstances[i])
|
||||
ret++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void pathInit()
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ extern QString emuDirectory;
|
|||
|
||||
bool createEmuInstance();
|
||||
void deleteEmuInstance(int id);
|
||||
void deleteAllEmuInstances();
|
||||
void deleteAllEmuInstances(int first = 0);
|
||||
int numEmuInstances();
|
||||
|
||||
#endif // MAIN_H
|
||||
|
|
Loading…
Reference in New Issue