Added pause/resume functionality
This commit is contained in:
parent
20aee963c9
commit
99e2e1bf0b
7 changed files with 101 additions and 68 deletions
|
@ -96,6 +96,13 @@ void Console::Run()
|
||||||
|
|
||||||
WaitForLock();
|
WaitForLock();
|
||||||
|
|
||||||
|
if(_paused && !_stopFlag && !_debugger) {
|
||||||
|
WaitForPauseEnd();
|
||||||
|
if(_stopFlag) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
frameLimiter.ProcessFrame();
|
frameLimiter.ProcessFrame();
|
||||||
frameLimiter.WaitForNextFrame();
|
frameLimiter.WaitForNextFrame();
|
||||||
|
|
||||||
|
@ -189,6 +196,7 @@ void Console::LoadRom(VirtualFile romFile, VirtualFile patchFile)
|
||||||
//GetDebugger();
|
//GetDebugger();
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
_paused = false;
|
||||||
_notificationManager->SendNotification(ConsoleNotificationType::GameLoaded);
|
_notificationManager->SendNotification(ConsoleNotificationType::GameLoaded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,6 +223,56 @@ double Console::GetFrameDelay()
|
||||||
return frameDelay;
|
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()
|
ConsoleLock Console::AcquireLock()
|
||||||
{
|
{
|
||||||
return ConsoleLock(this);
|
return ConsoleLock(this);
|
||||||
|
|
|
@ -56,9 +56,11 @@ private:
|
||||||
|
|
||||||
SimpleLock _debuggerLock;
|
SimpleLock _debuggerLock;
|
||||||
atomic<bool> _stopFlag;
|
atomic<bool> _stopFlag;
|
||||||
|
atomic<bool> _paused;
|
||||||
|
|
||||||
double GetFrameDelay();
|
double GetFrameDelay();
|
||||||
void WaitForLock();
|
void WaitForLock();
|
||||||
|
void WaitForPauseEnd();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~Console();
|
~Console();
|
||||||
|
@ -69,6 +71,10 @@ public:
|
||||||
void Run();
|
void Run();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
void Pause();
|
||||||
|
void Resume();
|
||||||
|
bool IsPaused();
|
||||||
|
|
||||||
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
|
void LoadRom(VirtualFile romFile, VirtualFile patchFile);
|
||||||
RomInfo GetRomInfo();
|
RomInfo GetRomInfo();
|
||||||
|
|
||||||
|
|
|
@ -109,16 +109,27 @@ extern "C" {
|
||||||
|
|
||||||
DllExport void __stdcall Run()
|
DllExport void __stdcall Run()
|
||||||
{
|
{
|
||||||
if(_console) {
|
|
||||||
_console->Run();
|
_console->Run();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
DllExport void __stdcall Stop()
|
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()
|
DllExport void __stdcall Release()
|
||||||
|
|
|
@ -64,7 +64,7 @@ namespace Mesen.GUI.Emulation
|
||||||
//TODO bool restoreFullscreen = _frmFullscreenRenderer != null;
|
//TODO bool restoreFullscreen = _frmFullscreenRenderer != null;
|
||||||
|
|
||||||
switch(shortcut) {
|
switch(shortcut) {
|
||||||
case EmulatorShortcut.Pause: PauseEmu(); break;
|
case EmulatorShortcut.Pause: TogglePause(); break;
|
||||||
case EmulatorShortcut.Reset: ResetEmu(); break;
|
case EmulatorShortcut.Reset: ResetEmu(); break;
|
||||||
case EmulatorShortcut.PowerCycle: PowerCycleEmu(); break;
|
case EmulatorShortcut.PowerCycle: PowerCycleEmu(); break;
|
||||||
case EmulatorShortcut.PowerOff: Task.Run(() => EmuApi.Stop()); break;
|
case EmulatorShortcut.PowerOff: Task.Run(() => EmuApi.Stop()); break;
|
||||||
|
@ -264,9 +264,13 @@ namespace Mesen.GUI.Emulation
|
||||||
ConfigManager.ApplyChanges();
|
ConfigManager.ApplyChanges();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PauseEmu()
|
private void TogglePause()
|
||||||
{
|
{
|
||||||
//TODO
|
if(EmuApi.IsPaused()) {
|
||||||
|
EmuApi.Resume();
|
||||||
|
} else {
|
||||||
|
EmuApi.Pause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ResetEmu()
|
private void ResetEmu()
|
||||||
|
|
|
@ -29,6 +29,10 @@ namespace Mesen.GUI
|
||||||
[DllImport(DllPath)] public static extern void Run();
|
[DllImport(DllPath)] public static extern void Run();
|
||||||
[DllImport(DllPath)] public static extern void Stop();
|
[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 TakeScreenshot();
|
||||||
|
|
||||||
[DllImport(DllPath)] public static extern void LoadRom(
|
[DllImport(DllPath)] public static extern void LoadRom(
|
||||||
|
|
|
@ -536,64 +536,16 @@ void Renderer::DrawScreen()
|
||||||
_spriteBatch->Draw(_pTextureSrv, destRect);
|
_spriteBatch->Draw(_pTextureSrv, destRect);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DrawPauseScreen(bool disableOverlay)
|
void Renderer::DrawPauseScreen()
|
||||||
{
|
{
|
||||||
if(disableOverlay) {
|
const static XMVECTORF32 transparentBlue = { { { 1.0f, 0.6f, 0.0f, 0.66f } } };
|
||||||
const static XMVECTORF32 transparentBlue = { { { 0.415686309f, 0.352941185f, 0.803921640f, 0.66f } } };
|
|
||||||
DrawString("I", 15, 15, transparentBlue, 2.0f, _font.get());
|
DrawString("I", 15, 15, transparentBlue, 2.0f, _font.get());
|
||||||
DrawString("I", 32, 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());
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Render()
|
void Renderer::Render()
|
||||||
{
|
{
|
||||||
//TODO
|
bool paused = _console->IsPaused();
|
||||||
/*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;
|
|
||||||
|
|
||||||
if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) {
|
if(_noUpdateCount > 10 || _frameChanged || paused || IsMessageShown()) {
|
||||||
_noUpdateCount = 0;
|
_noUpdateCount = 0;
|
||||||
|
@ -620,12 +572,10 @@ void Renderer::Render()
|
||||||
//Draw screen
|
//Draw screen
|
||||||
DrawScreen();
|
DrawScreen();
|
||||||
|
|
||||||
//TODO
|
|
||||||
/*
|
|
||||||
if(paused) {
|
if(paused) {
|
||||||
DrawPauseScreen(disableOverlay);
|
DrawPauseScreen();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
if(_console->IsRunning()) {
|
if(_console->IsRunning()) {
|
||||||
DrawCounters();
|
DrawCounters();
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ private:
|
||||||
ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height);
|
ID3D11Texture2D* CreateTexture(uint32_t width, uint32_t height);
|
||||||
ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture);
|
ID3D11ShaderResourceView* GetShaderResourceView(ID3D11Texture2D* texture);
|
||||||
void DrawScreen();
|
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(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);
|
void DrawString(std::wstring message, float x, float y, DirectX::FXMVECTOR color, float scale, SpriteFont* font = nullptr);
|
||||||
|
|
Loading…
Add table
Reference in a new issue