From ca0a76af1a3671b17cb745293c87eaebe639d9bb Mon Sep 17 00:00:00 2001 From: Arisotura Date: Sat, 11 Mar 2023 13:46:29 +0100 Subject: [PATCH] make cross-instance pause work without being a shitshow --- src/frontend/qt_sdl/IPC.cpp | 50 +++++++++++++++++++++++++----------- src/frontend/qt_sdl/IPC.h | 3 +++ src/frontend/qt_sdl/main.cpp | 28 +++++++++++++++++++- src/frontend/qt_sdl/main.h | 3 +++ 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/frontend/qt_sdl/IPC.cpp b/src/frontend/qt_sdl/IPC.cpp index 05c7f82e..0ceb7b2c 100644 --- a/src/frontend/qt_sdl/IPC.cpp +++ b/src/frontend/qt_sdl/IPC.cpp @@ -61,6 +61,8 @@ const u32 kMaxCommandSize = 0x800; const u32 kCommandStart = sizeof(BufferHeader); const u32 kCommandEnd = kBufferSize; +bool CmdRecvFlags[Cmd_MAX]; + void Init() { @@ -109,6 +111,8 @@ void Init() } Buffer->unlock(); + memset(CmdRecvFlags, 0, sizeof(CmdRecvFlags)); + printf("IPC: instance ID %d\n", InstanceID); } @@ -185,6 +189,8 @@ void FIFOWrite(void* buf, int len) void Process() { + memset(CmdRecvFlags, 0, sizeof(CmdRecvFlags)); + Buffer->lock(); u8* data = (u8*)Buffer->data(); BufferHeader* header = (BufferHeader*)&data[0]; @@ -211,13 +217,18 @@ void Process() if (!(cmdheader.Recipients & (1<= Cmd_MAX) + continue; + // handle this command - switch (cmdheader.Command) + /*switch (cmdheader.Command) { case Cmd_Pause: Input::ExtHotkeyPress(HK_Pause); break; - } + }*/ + CmdRecvFlags[cmdheader.Command] = true; + // TODO: store the command data, for future commands that will need it } Buffer->unlock(); @@ -225,6 +236,22 @@ void Process() 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(); u8* data = (u8*)Buffer->data(); BufferHeader* header = (BufferHeader*)&data[0]; @@ -237,19 +264,6 @@ bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata) 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; cmdheader.Magic = 0x4D434C4D; cmdheader.SenderID = InstanceID; @@ -264,4 +278,10 @@ bool SendCommand(u16 recipients, u16 command, u16 len, void* cmddata) return true; } +bool CommandReceived(u16 command) +{ + if (command >= Cmd_MAX) return false; + return CmdRecvFlags[command]; +} + } diff --git a/src/frontend/qt_sdl/IPC.h b/src/frontend/qt_sdl/IPC.h index 80546ec1..5016836d 100644 --- a/src/frontend/qt_sdl/IPC.h +++ b/src/frontend/qt_sdl/IPC.h @@ -27,6 +27,8 @@ namespace IPC enum { Cmd_Pause = 1, + + Cmd_MAX }; extern int InstanceID; @@ -37,6 +39,7 @@ void DeInit(); void Process(); bool SendCommand(u16 recipients, u16 command, u16 len, void* data); +bool CommandReceived(u16 command); } diff --git a/src/frontend/qt_sdl/main.cpp b/src/frontend/qt_sdl/main.cpp index 8436068d..10d459c6 100644 --- a/src/frontend/qt_sdl/main.cpp +++ b/src/frontend/qt_sdl/main.cpp @@ -198,6 +198,8 @@ EmuThread::EmuThread(QObject* parent) : QThread(parent) connect(this, SIGNAL(swapScreensToggle()), mainWindow->actScreenSwap, SLOT(trigger())); connect(this, SIGNAL(screenEmphasisToggle()), mainWindow, SLOT(onScreenEmphasisToggled())); + connect(this, SIGNAL(windowIPCPause()), mainWindow, SLOT(onIPCPause())); + static_cast(mainWindow->panel)->transferLayout(this); } @@ -359,6 +361,8 @@ void EmuThread::run() { IPC::Process(); + if (IPC::CommandReceived(IPC::Cmd_Pause)) emit windowIPCPause(); + Input::Process(); if (Input::HotkeyPressed(HK_FastForwardToggle)) emit windowLimitFPSChange(); @@ -2707,10 +2711,32 @@ void MainWindow::onPause(bool checked) pausedManually = false; } - if (Platform::InstanceID()==0) // HAX 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() { if (!RunningSomething) return; diff --git a/src/frontend/qt_sdl/main.h b/src/frontend/qt_sdl/main.h index 073a4da0..f1adaeec 100644 --- a/src/frontend/qt_sdl/main.h +++ b/src/frontend/qt_sdl/main.h @@ -78,6 +78,8 @@ signals: void windowEmuReset(); void windowEmuFrameStep(); + void windowIPCPause(); + void windowLimitFPSChange(); void screenLayoutChange(); @@ -296,6 +298,7 @@ private slots: void onQuit(); void onPause(bool checked); + void onIPCPause(); void onReset(); void onStop(); void onFrameStep();