Added pause/resume functionality

This commit is contained in:
Sour 2019-03-12 13:13:32 -04:00
parent 20aee963c9
commit 99e2e1bf0b
7 changed files with 101 additions and 68 deletions

View file

@ -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 = _debugger;
if(debugger) {
debugger->Step(1);
} else {
_paused = true;
}
}
void Console::Resume()
{
shared_ptr<Debugger> debugger = _debugger;
if(debugger) {
debugger->Run();
} else {
_paused = false;
}
}
bool Console::IsPaused()
{
shared_ptr<Debugger> 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<int, std::milli>(30));
}
PlatformUtilities::DisableScreensaver();
_runLock.Acquire();
_notificationManager->SendNotification(ConsoleNotificationType::GameResumed);
}
ConsoleLock Console::AcquireLock()
{
return ConsoleLock(this);

View file

@ -56,9 +56,11 @@ private:
SimpleLock _debuggerLock;
atomic<bool> _stopFlag;
atomic<bool> _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();

View file

@ -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();

View file

@ -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()

View file

@ -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(

View file

@ -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> 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();
}

View file

@ -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);