diff --git a/Core/Console.cpp b/Core/Console.cpp index 1a32f23..d8e3555 100644 --- a/Core/Console.cpp +++ b/Core/Console.cpp @@ -96,6 +96,13 @@ void Console::Run() WaitForLock(); + if(_paused && !_stopFlag && !_debugger) { + WaitForPauseEnd(); + if(_stopFlag) { + break; + } + } + frameLimiter.ProcessFrame(); frameLimiter.WaitForNextFrame(); @@ -189,6 +196,7 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile) //GetDebugger(); //} + _paused = false; _notificationManager->SendNotification(ConsoleNotificationType::GameLoaded); } } @@ -215,6 +223,56 @@ double Console::GetFrameDelay() return frameDelay; } +void Console::Pause() +{ + shared_ptr debugger = _debugger; + if(debugger) { + debugger->Step(1); + } else { + _paused = true; + } +} + +void Console::Resume() +{ + shared_ptr debugger = _debugger; + if(debugger) { + debugger->Run(); + } else { + _paused = false; + } +} + +bool Console::IsPaused() +{ + shared_ptr debugger = _debugger; + if(debugger) { + return debugger->IsExecutionStopped(); + } else { + return _paused; + } +} + +void Console::WaitForPauseEnd() +{ + _notificationManager->SendNotification(ConsoleNotificationType::GamePaused); + + //Prevent audio from looping endlessly while game is paused + _soundMixer->StopAudio(); + _runLock.Release(); + + PlatformUtilities::EnableScreensaver(); + PlatformUtilities::RestoreTimerResolution(); + while(_paused && !_stopFlag && !_debugger) { + //Sleep until emulation is resumed + std::this_thread::sleep_for(std::chrono::duration(30)); + } + + PlatformUtilities::DisableScreensaver(); + _runLock.Acquire(); + _notificationManager->SendNotification(ConsoleNotificationType::GameResumed); +} + ConsoleLock Console::AcquireLock() { return ConsoleLock(this); diff --git a/Core/Console.h b/Core/Console.h index dc70725..e2a073d 100644 --- a/Core/Console.h +++ b/Core/Console.h @@ -56,9 +56,11 @@ private: SimpleLock _debuggerLock; atomic _stopFlag; + atomic _paused; double GetFrameDelay(); void WaitForLock(); + void WaitForPauseEnd(); public: ~Console(); @@ -69,6 +71,10 @@ public: void Run(); void Stop(); + void Pause(); + void Resume(); + bool IsPaused(); + void LoadRom(VirtualFile romFile, VirtualFile patchFile); RomInfo GetRomInfo(); diff --git a/InteropDLL/EmuApiWrapper.cpp b/InteropDLL/EmuApiWrapper.cpp index 1439c82..092eb49 100644 --- a/InteropDLL/EmuApiWrapper.cpp +++ b/InteropDLL/EmuApiWrapper.cpp @@ -109,18 +109,29 @@ extern "C" { DllExport void __stdcall Run() { - if(_console) { - _console->Run(); - } + _console->Run(); } DllExport void __stdcall Stop() { - if(_console) { - _console->Stop(); - } + _console->Stop(); } - + + DllExport void __stdcall Pause() + { + _console->Pause(); + } + + DllExport void __stdcall Resume() + { + _console->Resume(); + } + + DllExport void __stdcall IsPaused() + { + _console->IsPaused(); + } + DllExport void __stdcall Release() { _console->Stop(); diff --git a/UI/Emulation/ShortcutHandler.cs b/UI/Emulation/ShortcutHandler.cs index 9542c9d..91a298d 100644 --- a/UI/Emulation/ShortcutHandler.cs +++ b/UI/Emulation/ShortcutHandler.cs @@ -64,7 +64,7 @@ namespace Mesen.GUI.Emulation //TODO bool restoreFullscreen = _frmFullscreenRenderer != null; switch(shortcut) { - case EmulatorShortcut.Pause: PauseEmu(); break; + case EmulatorShortcut.Pause: TogglePause(); break; case EmulatorShortcut.Reset: ResetEmu(); break; case EmulatorShortcut.PowerCycle: PowerCycleEmu(); break; case EmulatorShortcut.PowerOff: Task.Run(() => EmuApi.Stop()); break; @@ -264,9 +264,13 @@ namespace Mesen.GUI.Emulation ConfigManager.ApplyChanges(); } - private void PauseEmu() + private void TogglePause() { - //TODO + if(EmuApi.IsPaused()) { + EmuApi.Resume(); + } else { + EmuApi.Pause(); + } } private void ResetEmu() diff --git a/UI/Interop/EmuApi.cs b/UI/Interop/EmuApi.cs index 9133ca2..2ec3aff 100644 --- a/UI/Interop/EmuApi.cs +++ b/UI/Interop/EmuApi.cs @@ -29,6 +29,10 @@ namespace Mesen.GUI [DllImport(DllPath)] public static extern void Run(); [DllImport(DllPath)] public static extern void Stop(); + [DllImport(DllPath)] public static extern void Pause(); + [DllImport(DllPath)] public static extern void Resume(); + [DllImport(DllPath)] [return: MarshalAs(UnmanagedType.I1)] public static extern bool IsPaused(); + [DllImport(DllPath)] public static extern void TakeScreenshot(); [DllImport(DllPath)] public static extern void LoadRom( diff --git a/Windows/Renderer.cpp b/Windows/Renderer.cpp index e3ac04b..23a16c0 100644 --- a/Windows/Renderer.cpp +++ b/Windows/Renderer.cpp @@ -536,64 +536,16 @@ void Renderer::DrawScreen() _spriteBatch->Draw(_pTextureSrv, destRect); } -void Renderer::DrawPauseScreen(bool disableOverlay) +void Renderer::DrawPauseScreen() { - if(disableOverlay) { - const static XMVECTORF32 transparentBlue = { { { 0.415686309f, 0.352941185f, 0.803921640f, 0.66f } } }; - DrawString("I", 15, 15, transparentBlue, 2.0f, _font.get()); - DrawString("I", 32, 15, transparentBlue, 2.0f, _font.get()); - } else { - RECT destRect; - destRect.left = 0; - destRect.top = 0; - destRect.right = _realScreenWidth; - destRect.bottom = _realScreenHeight; - - D3D11_MAPPED_SUBRESOURCE dd; - HRESULT hr = _pDeviceContext->Map(_overlayTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &dd); - if(FAILED(hr)) { - MessageManager::Log("(DrawPauseScreen) DeviceContext::Map() failed - Error:" + std::to_string(hr)); - return; - } - - uint8_t* surfacePointer = (uint8_t*)dd.pData; - for(uint32_t i = 0, len = 8; i < len; i++) { - //Gray transparent overlay - for(int j = 0; j < 8; j++) { - ((uint32_t*)surfacePointer)[j] = 0xAA222222; - } - surfacePointer += dd.RowPitch; - } - _pDeviceContext->Unmap(_overlayTexture, 0); - - _spriteBatch->Draw(_pOverlaySrv, destRect); - - XMVECTOR stringDimensions = _largeFont->MeasureString(L"PAUSE"); - float x = (float)_screenWidth / 2 - stringDimensions.m128_f32[0] / 2; - float y = (float)_screenHeight / 2 - stringDimensions.m128_f32[1] / 2 - 8; - DrawString("PAUSE", x, y, Colors::AntiqueWhite, 1.0f, _largeFont.get()); - - //TODO - /*string utf8Message = _console->GetSettings()->GetPauseScreenMessage(); - if(utf8Message.size() > 0) { - std::wstring message = utf8::utf8::decode(utf8Message); - float width = MeasureString(message); - DrawString(message, (float)_screenWidth - width - 20, (float)_screenHeight - 40, Colors::AntiqueWhite, 1.0f, _font.get()); - }*/ - } + const static XMVECTORF32 transparentBlue = { { { 1.0f, 0.6f, 0.0f, 0.66f } } }; + DrawString("I", 15, 15, transparentBlue, 2.0f, _font.get()); + DrawString("I", 32, 15, transparentBlue, 2.0f, _font.get()); } void Renderer::Render() { - //TODO - /*bool paused = _console->IsPaused() && _console->IsRunning(); - bool disableOverlay = _console->GetSettings()->CheckFlag(EmulationFlags::HidePauseOverlay); - shared_ptr debugger = _console->GetDebugger(false); - if(debugger && debugger->IsExecutionStopped()) { - paused = debugger->IsPauseIconShown(); - disableOverlay = true; - }*/ - bool paused = false; + bool paused = _console->IsPaused(); if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) { _noUpdateCount = 0; @@ -620,12 +572,10 @@ void Renderer::Render() //Draw screen DrawScreen(); - //TODO - /* if(paused) { - DrawPauseScreen(disableOverlay); + DrawPauseScreen(); } - */ + if(_console->IsRunning()) { DrawCounters(); } diff --git a/Windows/Renderer.h b/Windows/Renderer.h index b8e7d6e..0d6e2bb 100644 --- a/Windows/Renderer.h +++ b/Windows/Renderer.h @@ -76,7 +76,7 @@ private: ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height); ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture); void DrawScreen(); - void DrawPauseScreen(bool disableOverlay); + void DrawPauseScreen(); void DrawString(string message, float x, float y, DirectX::FXMVECTOR color, float scale, SpriteFont* font = nullptr); void DrawString(std::wstring message, float x, float y, DirectX::FXMVECTOR color, float scale, SpriteFont* font = nullptr);