mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-27 00:00:07 -06:00
make cross-instance pause work without being a shitshow
This commit is contained in:
@ -61,6 +61,8 @@ const u32 kMaxCommandSize = 0x800;
|
|||||||
const u32 kCommandStart = sizeof(BufferHeader);
|
const u32 kCommandStart = sizeof(BufferHeader);
|
||||||
const u32 kCommandEnd = kBufferSize;
|
const u32 kCommandEnd = kBufferSize;
|
||||||
|
|
||||||
|
bool CmdRecvFlags[Cmd_MAX];
|
||||||
|
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
@ -109,6 +111,8 @@ void Init()
|
|||||||
}
|
}
|
||||||
Buffer->unlock();
|
Buffer->unlock();
|
||||||
|
|
||||||
|
memset(CmdRecvFlags, 0, sizeof(CmdRecvFlags));
|
||||||
|
|
||||||
printf("IPC: instance ID %d\n", InstanceID);
|
printf("IPC: instance ID %d\n", InstanceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,6 +189,8 @@ void FIFOWrite(void* buf, int len)
|
|||||||
|
|
||||||
void Process()
|
void Process()
|
||||||
{
|
{
|
||||||
|
memset(CmdRecvFlags, 0, sizeof(CmdRecvFlags));
|
||||||
|
|
||||||
Buffer->lock();
|
Buffer->lock();
|
||||||
u8* data = (u8*)Buffer->data();
|
u8* data = (u8*)Buffer->data();
|
||||||
BufferHeader* header = (BufferHeader*)&data[0];
|
BufferHeader* header = (BufferHeader*)&data[0];
|
||||||
@ -211,13 +217,18 @@ void Process()
|
|||||||
if (!(cmdheader.Recipients & (1<<InstanceID)))
|
if (!(cmdheader.Recipients & (1<<InstanceID)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (cmdheader.Command >= Cmd_MAX)
|
||||||
|
continue;
|
||||||
|
|
||||||
// handle this command
|
// handle this command
|
||||||
switch (cmdheader.Command)
|
/*switch (cmdheader.Command)
|
||||||
{
|
{
|
||||||
case Cmd_Pause:
|
case Cmd_Pause:
|
||||||
Input::ExtHotkeyPress(HK_Pause);
|
Input::ExtHotkeyPress(HK_Pause);
|
||||||
break;
|
break;
|
||||||
}
|
}*/
|
||||||
|
CmdRecvFlags[cmdheader.Command] = true;
|
||||||
|
// TODO: store the command data, for future commands that will need it
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer->unlock();
|
Buffer->unlock();
|
||||||
@ -225,6 +236,22 @@ void Process()
|
|||||||
|
|
||||||
bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata)
|
bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata)
|
||||||
{
|
{
|
||||||
|
if (command >= Cmd_MAX)
|
||||||
|
{
|
||||||
|
printf("IPC: invalid command %d\n", command);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len && cmddata==nullptr)
|
||||||
|
{
|
||||||
|
printf("IPC: ????? sending command with NULL buffer\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len > kMaxCommandSize)
|
||||||
|
{
|
||||||
|
printf("IPC: command too long\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Buffer->lock();
|
Buffer->lock();
|
||||||
u8* data = (u8*)Buffer->data();
|
u8* data = (u8*)Buffer->data();
|
||||||
BufferHeader* header = (BufferHeader*)&data[0];
|
BufferHeader* header = (BufferHeader*)&data[0];
|
||||||
@ -237,19 +264,6 @@ bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len && cmddata==nullptr)
|
|
||||||
{
|
|
||||||
printf("IPC: ????? sending command with NULL buffer\n");
|
|
||||||
Buffer->unlock();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (len > kMaxCommandSize)
|
|
||||||
{
|
|
||||||
printf("IPC: command too long\n");
|
|
||||||
Buffer->unlock();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CommandHeader cmdheader;
|
CommandHeader cmdheader;
|
||||||
cmdheader.Magic = 0x4D434C4D;
|
cmdheader.Magic = 0x4D434C4D;
|
||||||
cmdheader.SenderID = InstanceID;
|
cmdheader.SenderID = InstanceID;
|
||||||
@ -264,4 +278,10 @@ bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandReceived(u16 command)
|
||||||
|
{
|
||||||
|
if (command >= Cmd_MAX) return false;
|
||||||
|
return CmdRecvFlags[command];
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,8 @@ namespace IPC
|
|||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
Cmd_Pause = 1,
|
Cmd_Pause = 1,
|
||||||
|
|
||||||
|
Cmd_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int InstanceID;
|
extern int InstanceID;
|
||||||
@ -37,6 +39,7 @@ void DeInit();
|
|||||||
void Process();
|
void Process();
|
||||||
|
|
||||||
bool SendCommand(u16 recipients, u16 command, u16 len, void* data);
|
bool SendCommand(u16 recipients, u16 command, u16 len, void* data);
|
||||||
|
bool CommandReceived(u16 command);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,6 +198,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent)
|
|||||||
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
|
connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger()));
|
||||||
connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled()));
|
connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled()));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(windowIPCPause()), mainWindow, SLOT(onIPCPause()));
|
||||||
|
|
||||||
static_cast<ScreenPanelGL*>(mainWindow->panel)->transferLayout(this);
|
static_cast<ScreenPanelGL*>(mainWindow->panel)->transferLayout(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -359,6 +361,8 @@ void EmuThread::run()
|
|||||||
{
|
{
|
||||||
IPC::Process();
|
IPC::Process();
|
||||||
|
|
||||||
|
if (IPC::CommandReceived(IPC::Cmd_Pause)) emit windowIPCPause();
|
||||||
|
|
||||||
Input::Process();
|
Input::Process();
|
||||||
|
|
||||||
if (Input::HotkeyPressed(HK_FastForwardToggle)) emit windowLimitFPSChange();
|
if (Input::HotkeyPressed(HK_FastForwardToggle)) emit windowLimitFPSChange();
|
||||||
@ -2707,10 +2711,32 @@ void MainWindow::onPause(bool checked)
|
|||||||
pausedManually = false;
|
pausedManually = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Platform::InstanceID()==0) // HAX
|
|
||||||
IPC::SendCommand(0xFFFF, IPC::Cmd_Pause, 0, nullptr);
|
IPC::SendCommand(0xFFFF, IPC::Cmd_Pause, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::onIPCPause()
|
||||||
|
{
|
||||||
|
// for IPC, using the normal way to trigger a pause (actPause->trigger())
|
||||||
|
// isn't viable, because it would lead to broadcasting more IPC 'pause' messages
|
||||||
|
// so we have to replicate it this way
|
||||||
|
|
||||||
|
actPause->toggle(); // changes visual state, without triggering onPause()
|
||||||
|
bool checked = actPause->isChecked();
|
||||||
|
|
||||||
|
if (checked)
|
||||||
|
{
|
||||||
|
emuThread->emuPause();
|
||||||
|
OSD::AddMessage(0, "Paused");
|
||||||
|
pausedManually = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emuThread->emuUnpause();
|
||||||
|
OSD::AddMessage(0, "Resumed");
|
||||||
|
pausedManually = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::onReset()
|
void MainWindow::onReset()
|
||||||
{
|
{
|
||||||
if (!RunningSomething) return;
|
if (!RunningSomething) return;
|
||||||
|
@ -78,6 +78,8 @@ signals:
|
|||||||
void windowEmuReset();
|
void windowEmuReset();
|
||||||
void windowEmuFrameStep();
|
void windowEmuFrameStep();
|
||||||
|
|
||||||
|
void windowIPCPause();
|
||||||
|
|
||||||
void windowLimitFPSChange();
|
void windowLimitFPSChange();
|
||||||
|
|
||||||
void screenLayoutChange();
|
void screenLayoutChange();
|
||||||
@ -296,6 +298,7 @@ private slots:
|
|||||||
void onQuit();
|
void onQuit();
|
||||||
|
|
||||||
void onPause(bool checked);
|
void onPause(bool checked);
|
||||||
|
void onIPCPause();
|
||||||
void onReset();
|
void onReset();
|
||||||
void onStop();
|
void onStop();
|
||||||
void onFrameStep();
|
void onFrameStep();
|
||||||
|
Reference in New Issue
Block a user