From eb80802d3ad3c2dcdf543f1713ccddd685cb63c7 Mon Sep 17 00:00:00 2001 From: Sour Date: Sun, 29 May 2022 12:17:51 -0400 Subject: [PATCH] UI: Keep emulation paused when using reset/power cycle, prevent game from running when debugger is opened while paused --- Core/Debugger/Debugger.cpp | 5 +++++ Core/PCE/PceConsole.cpp | 2 ++ Core/Shared/Emulator.cpp | 9 ++++++++- Core/Shared/Interfaces/IRenderingDevice.h | 1 + Core/Shared/SystemActionManager.h | 5 +++++ Core/Shared/Video/VideoDecoder.cpp | 10 +++------- Core/Shared/Video/VideoRenderer.cpp | 7 +++++++ Core/Shared/Video/VideoRenderer.h | 1 + Linux/SdlRenderer.cpp | 14 ++++++++++++-- Linux/SdlRenderer.h | 1 + Windows/Renderer.cpp | 12 ++++++++++++ Windows/Renderer.h | 1 + 12 files changed, 58 insertions(+), 10 deletions(-) diff --git a/Core/Debugger/Debugger.cpp b/Core/Debugger/Debugger.cpp index 75191918..03f33dac 100644 --- a/Core/Debugger/Debugger.cpp +++ b/Core/Debugger/Debugger.cpp @@ -102,6 +102,11 @@ Debugger::Debugger(Emulator* emu, IConsole* console) RefreshCodeCache(); + if(_emu->IsPaused()) { + //Break on the current instruction if emulation was already paused + Step(_mainCpuType, 1, StepType::Step); + } + _executionStopped = false; #ifdef _DEBUG diff --git a/Core/PCE/PceConsole.cpp b/Core/PCE/PceConsole.cpp index bff966c5..2497f294 100644 --- a/Core/PCE/PceConsole.cpp +++ b/Core/PCE/PceConsole.cpp @@ -33,6 +33,8 @@ void PceConsole::Stop() void PceConsole::Reset() { + //The PC Engine has no reset button, behave like power cycle + _emu->ReloadRom(true); } void PceConsole::OnBeforeRun() diff --git a/Core/Shared/Emulator.cpp b/Core/Shared/Emulator.cpp index d23b1e49..c7647233 100644 --- a/Core/Shared/Emulator.cpp +++ b/Core/Shared/Emulator.cpp @@ -313,6 +313,8 @@ void Emulator::Reset() _console->Reset(); GetControlManager()->UpdateInputState(); + _videoRenderer->ClearFrame(); + _notificationManager->SendNotification(ConsoleNotificationType::GameReset); ProcessEvent(EventType::Reset); @@ -473,7 +475,6 @@ bool Emulator::LoadRom(VirtualFile romFile, VirtualFile patchFile, bool stopRom, _threadPaused = true; _notificationManager->SendNotification(ConsoleNotificationType::GameLoaded, (void*)forPowerCycle); _threadPaused = false; - _paused = false; if(!forPowerCycle && !_audioPlayerHud) { string modelName = _console->GetRegion() == ConsoleRegion::Pal ? "PAL" : "NTSC"; @@ -671,9 +672,15 @@ void Emulator::WaitForPauseEnd() PlatformUtilities::EnableScreensaver(); PlatformUtilities::RestoreTimerResolution(); + while(_paused && !_stopFlag && !_debugger) { //Sleep until emulation is resumed std::this_thread::sleep_for(std::chrono::duration(30)); + + if(_systemActionManager->IsResetPending()) { + //Reset/power cycle was pressed, stop waiting and process it now + break; + } } PlatformUtilities::DisableScreensaver(); diff --git a/Core/Shared/Interfaces/IRenderingDevice.h b/Core/Shared/Interfaces/IRenderingDevice.h index fef37799..7bcee161 100644 --- a/Core/Shared/Interfaces/IRenderingDevice.h +++ b/Core/Shared/Interfaces/IRenderingDevice.h @@ -10,6 +10,7 @@ class IRenderingDevice public: virtual ~IRenderingDevice() {} virtual void UpdateFrame(RenderedFrame& frame) = 0; + virtual void ClearFrame() = 0; virtual void Render(uint32_t* hudBuffer, uint32_t width, uint32_t height) = 0; virtual void Reset() = 0; virtual void SetFullscreenMode(bool fullscreen, void* windowHandle, uint32_t monitorWidth, uint32_t monitorHeight) = 0; diff --git a/Core/Shared/SystemActionManager.h b/Core/Shared/SystemActionManager.h index 52e182b8..40d2f70b 100644 --- a/Core/Shared/SystemActionManager.h +++ b/Core/Shared/SystemActionManager.h @@ -63,6 +63,11 @@ public: return false; } + bool IsResetPending() + { + return _needReset || _needPowerCycle; + } + bool IsResetPressed() { return IsPressed(SystemActionManager::Buttons::ResetButton); diff --git a/Core/Shared/Video/VideoDecoder.cpp b/Core/Shared/Video/VideoDecoder.cpp index f8a6ea03..df0dfa80 100644 --- a/Core/Shared/Video/VideoDecoder.cpp +++ b/Core/Shared/Video/VideoDecoder.cpp @@ -210,6 +210,8 @@ void VideoDecoder::StartThread() _frameCount = 0; _waitForFrame.Reset(); + _emu->GetVideoRenderer()->ClearFrame(); + _decodeThread.reset(new thread(&VideoDecoder::DecodeThread, this)); } #endif @@ -227,13 +229,7 @@ void VideoDecoder::StopThread() _decodeThread.reset(); //Clear whole screen - if(_frameCount > 0) { - vector outputBuffer(512 * 478, 0); - _frame.FrameBuffer = outputBuffer.data(); - memset(_frame.FrameBuffer, 0, 512 * 478 * 2); - DecodeFrame(); - _frame.FrameBuffer = nullptr; - } + _emu->GetVideoRenderer()->ClearFrame(); } #endif } diff --git a/Core/Shared/Video/VideoRenderer.cpp b/Core/Shared/Video/VideoRenderer.cpp index e9ed5b09..60be6356 100644 --- a/Core/Shared/Video/VideoRenderer.cpp +++ b/Core/Shared/Video/VideoRenderer.cpp @@ -123,6 +123,13 @@ void VideoRenderer::UpdateFrame(RenderedFrame& frame) } } +void VideoRenderer::ClearFrame() +{ + if(_renderer) { + _renderer->ClearFrame(); + } +} + void VideoRenderer::RegisterRenderingDevice(IRenderingDevice *renderer) { _renderer = renderer; diff --git a/Core/Shared/Video/VideoRenderer.h b/Core/Shared/Video/VideoRenderer.h index 937e19f9..ac8636dd 100644 --- a/Core/Shared/Video/VideoRenderer.h +++ b/Core/Shared/Video/VideoRenderer.h @@ -53,6 +53,7 @@ public: void StopThread(); void UpdateFrame(RenderedFrame& frame); + void ClearFrame(); void RegisterRenderingDevice(IRenderingDevice *renderer); void UnregisterRenderingDevice(IRenderingDevice *renderer); diff --git a/Linux/SdlRenderer.cpp b/Linux/SdlRenderer.cpp index 38a0eadc..1496f6b1 100644 --- a/Linux/SdlRenderer.cpp +++ b/Linux/SdlRenderer.cpp @@ -129,9 +129,20 @@ void SdlRenderer::SetScreenSize(uint32_t width, uint32_t height) } } +void SdlRenderer::ClearFrame() +{ + auto lock = _frameLock.AcquireSafe(); + if(_frameBuffer == nullptr) { + return; + } + + memset(_frameBuffer, 0, _requiredWidth * _requiredHeight * _bytesPerPixel); + _frameChanged = true; +} + void SdlRenderer::UpdateFrame(RenderedFrame& frame) { - _frameLock.Acquire(); + auto lock = _frameLock.AcquireSafe(); if(_frameBuffer == nullptr || _requiredWidth != frame.Width || _requiredHeight != frame.Height) { _requiredWidth = frame.Width; _requiredHeight = frame.Height; @@ -143,7 +154,6 @@ void SdlRenderer::UpdateFrame(RenderedFrame& frame) memcpy(_frameBuffer, frame.FrameBuffer, frame.Width * frame.Height *_bytesPerPixel); _frameChanged = true; - _frameLock.Release(); } void SdlRenderer::Render(uint32_t* hudBuffer, uint32_t width, uint32_t height) diff --git a/Linux/SdlRenderer.h b/Linux/SdlRenderer.h index 73c0b6b8..82ddc083 100644 --- a/Linux/SdlRenderer.h +++ b/Linux/SdlRenderer.h @@ -48,6 +48,7 @@ public: SdlRenderer(Emulator* emu, void* windowHandle, bool registerAsMessageManager); virtual ~SdlRenderer(); + void ClearFrame() override; void UpdateFrame(RenderedFrame& frame) override; void Render(uint32_t* hudBuffer, uint32_t width, uint32_t height) override; void Reset() override; diff --git a/Windows/Renderer.cpp b/Windows/Renderer.cpp index dd6e6f0d..cf583e4b 100644 --- a/Windows/Renderer.cpp +++ b/Windows/Renderer.cpp @@ -357,6 +357,18 @@ ID3D11ShaderResourceView* Renderer::GetShaderResourceView(ID3D11Texture2D* textu return shaderResourceView; } +void Renderer::ClearFrame() +{ + //Clear current output and display black frame + auto lock = _textureLock.AcquireSafe(); + if(_textureBuffer[0]) { + //_textureBuffer[0] may be null if directx failed to initialize properly + memset(_textureBuffer[0], 0, _emuFrameWidth * _emuFrameHeight * sizeof(uint32_t)); + _needFlip = true; + _frameChanged = true; + } +} + void Renderer::UpdateFrame(RenderedFrame& frame) { SetScreenSize(frame.Width, frame.Height); diff --git a/Windows/Renderer.h b/Windows/Renderer.h index 7b6e5c19..31ea18fc 100644 --- a/Windows/Renderer.h +++ b/Windows/Renderer.h @@ -83,6 +83,7 @@ public: void Reset(); void Render(uint32_t* hudBuffer, uint32_t hudWidth, uint32_t hudHeight); + void ClearFrame(); void UpdateFrame(RenderedFrame& frame); }; \ No newline at end of file