Skip to content

Commit

Permalink
VMManager: Defer reset when running
Browse files Browse the repository at this point in the history
Stops us resetting during the event test, which can leave things in a
pretty messed up state.
  • Loading branch information
stenzek authored and refractionpcsx2 committed Jan 25, 2023
1 parent 6a40959 commit 4c1d93a
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 1 deletion.
4 changes: 4 additions & 0 deletions pcsx2-qt/QtHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,10 @@ void EmuThread::executeVM()
VMManager::Execute();
continue;

case VMState::Resetting:
VMManager::Reset();
continue;

case VMState::Stopping:
destroyVM();
m_event_loop->processEvents(QEventLoop::AllEvents);
Expand Down
19 changes: 18 additions & 1 deletion pcsx2/VMManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ void VMManager::SetState(VMState state)
bool VMManager::HasValidVM()
{
const VMState state = s_state.load(std::memory_order_acquire);
return (state == VMState::Running || state == VMState::Paused);
return (state >= VMState::Running && state <= VMState::Resetting);
}

std::string VMManager::GetDiscPath()
Expand Down Expand Up @@ -1161,6 +1161,19 @@ void VMManager::Shutdown(bool save_resume_state)

void VMManager::Reset()
{
pxAssert(HasValidVM());

// If we're running, we're probably going to be executing this at event test time,
// at vsync, which happens in the middle of event handling. Resetting everything
// immediately here is a bad idea (tm), in fact, it breaks some games (e.g. TC:NYC).
// So, instead, we tell the rec to exit execution, _then_ reset. Paused is fine here,
// since the rec won't be running, so it's safe to immediately reset there.
if (s_state.load(std::memory_order_acquire) == VMState::Running)
{
s_state.store(VMState::Resetting, std::memory_order_release);
return;
}

#ifdef ENABLE_ACHIEVEMENTS
if (!Achievements::OnReset())
return;
Expand All @@ -1187,6 +1200,10 @@ void VMManager::Reset()
g_InputRecording.handleReset();
GetMTGS().PresentCurrentFrame();
}

// If we were paused, state won't be resetting, so don't flip back to running.
if (s_state.load(std::memory_order_acquire) == VMState::Resetting)
s_state.store(VMState::Running, std::memory_order_release);
}

std::string VMManager::GetSaveStateFileName(const char* game_serial, u32 game_crc, s32 slot)
Expand Down
1 change: 1 addition & 0 deletions pcsx2/VMManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ enum class VMState
Initializing,
Running,
Paused,
Resetting,
Stopping,
};

Expand Down

0 comments on commit 4c1d93a

Please sign in to comment.