diff --git a/Core/Core.cpp b/Core/Core.cpp index fefd4e04d..481c1f4b2 100644 --- a/Core/Core.cpp +++ b/Core/Core.cpp @@ -33,13 +33,24 @@ // HANDLE m_hStepEvent; event m_hStepEvent; recursive_mutex m_hStepMutex; +event m_hInactiveEvent; +recursive_mutex m_hInactiveMutex; // This can be read and written from ANYWHERE. volatile CoreState coreState = CORE_STEPPING; +// Note: intentionally not used for CORE_NEXTFRAME. +volatile bool coreStatePending = false; + +void Core_UpdateState(CoreState newState) +{ + if ((coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME) && newState != CORE_RUNNING) + coreStatePending = true; + coreState = newState; +} void Core_ErrorPause() { - coreState = CORE_ERROR; + Core_UpdateState(CORE_ERROR); } void Core_Pause() @@ -56,7 +67,7 @@ void Core_Halt(const char *msg) void Core_Stop() { - coreState = CORE_POWERDOWN; + Core_UpdateState(CORE_POWERDOWN); m_hStepEvent.notify_one(); } @@ -65,6 +76,23 @@ bool Core_IsStepping() return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN; } +bool Core_IsInactive() +{ + return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending; +} + +void Core_WaitInactive() +{ + while (!Core_IsInactive()) + m_hInactiveEvent.wait(m_hInactiveMutex); +} + +void Core_WaitInactive(int milliseconds) +{ + while (!Core_IsInactive()) + m_hInactiveEvent.wait_for(m_hInactiveMutex, milliseconds); +} + void Core_RunLoop() { while (!coreState) { @@ -110,6 +138,10 @@ reswitch: // We should never get here on Android. case CORE_STEPPING: + if (coreStatePending) + m_hInactiveEvent.notify_one(); + coreStatePending = false; + //1: wait for step command.. #if defined(USING_QT_UI) || defined(_DEBUG) host->UpdateDisassembly(); @@ -142,8 +174,13 @@ reswitch: case CORE_POWERDOWN: case CORE_ERROR: - case CORE_NEXTFRAME: //1: Exit loop!! + if (coreStatePending) + m_hInactiveEvent.notify_one(); + coreStatePending = false; + return; + + case CORE_NEXTFRAME: return; } } @@ -158,7 +195,7 @@ void Core_EnableStepping(bool step) #if defined(_DEBUG) host->SetDebugMode(true); #endif - coreState = CORE_STEPPING; + Core_UpdateState(CORE_STEPPING); } else { @@ -166,6 +203,7 @@ void Core_EnableStepping(bool step) host->SetDebugMode(false); #endif coreState = CORE_RUNNING; + coreStatePending = false; m_hStepEvent.notify_one(); } } diff --git a/Core/Core.h b/Core/Core.h index d9b07c7f6..2b9d359fa 100644 --- a/Core/Core.h +++ b/Core/Core.h @@ -43,5 +43,10 @@ enum CoreState CORE_NEXTFRAME, }; +void Core_UpdateState(CoreState newState); +bool Core_IsInactive(); +void Core_WaitInactive(); +void Core_WaitInactive(int milliseconds); + extern volatile CoreState coreState; diff --git a/Core/Debugger/Breakpoints.cpp b/Core/Debugger/Breakpoints.cpp index 3aed03de7..cbb960f8a 100644 --- a/Core/Debugger/Breakpoints.cpp +++ b/Core/Debugger/Breakpoints.cpp @@ -133,14 +133,14 @@ void CBreakPoints::AddBreakPoint(u32 _iAddress, bool temp) void CBreakPoints::InvalidateJit(u32 _iAddress) { // Don't want to clear cache while running, I think? - if (MIPSComp::jit && coreState == CORE_STEPPING) + if (MIPSComp::jit && Core_IsInactive()) MIPSComp::jit->ClearCacheAt(_iAddress); } void CBreakPoints::InvalidateJit() { // Don't want to clear cache while running, I think? - if (MIPSComp::jit && coreState == CORE_STEPPING) + if (MIPSComp::jit && Core_IsInactive()) MIPSComp::jit->ClearCache(); } diff --git a/Core/MIPS/MIPSInt.cpp b/Core/MIPS/MIPSInt.cpp index 479cff313..c8abb8193 100644 --- a/Core/MIPS/MIPSInt.cpp +++ b/Core/MIPS/MIPSInt.cpp @@ -187,7 +187,7 @@ namespace MIPSInt void Int_Break(u32 op) { ERROR_LOG(CPU, "BREAK!"); - coreState = CORE_STEPPING; + Core_UpdateState(CORE_STEPPING); PC += 4; } diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index 5b56caad7..3c3a38547 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -359,7 +359,7 @@ void Jit::WriteExitDestInEAX() // TODO: "Ignore" this so other threads can continue? if (g_Config.bIgnoreBadMemAccess) - MOV(32, M((void*)&coreState), Imm32(CORE_ERROR)); + ABI_CallFunctionA(thunks.ProtectFunction((void *) Core_UpdateState, 1), Imm32(CORE_ERROR)); JMP(asm_.dispatcherCheckCoreState, true); } else diff --git a/Core/MemMapFunctions.cpp b/Core/MemMapFunctions.cpp index d174cdb7e..dcc895d21 100644 --- a/Core/MemMapFunctions.cpp +++ b/Core/MemMapFunctions.cpp @@ -56,6 +56,10 @@ u8 *GetPointer(const u32 address) else { ERROR_LOG(MEMMAP, "Unknown GetPointer %08x PC %08x LR %08x", address, currentMIPS->pc, currentMIPS->r[MIPS_REG_RA]); + if (!g_Config.bIgnoreBadMemAccess) { + Core_EnableStepping(true); + host->SetDebugMode(true); + } return 0; } } diff --git a/Core/SaveState.cpp b/Core/SaveState.cpp index 8a450081c..a320c4e70 100644 --- a/Core/SaveState.cpp +++ b/Core/SaveState.cpp @@ -90,7 +90,7 @@ namespace SaveState // Don't actually run it until next CoreTiming::Advance(). // It's possible there might be a duplicate but it won't hurt us. - if (Core_IsStepping() && __KernelIsRunning()) + if (Core_IsInactive() && __KernelIsRunning()) { // Warning: this may run on a different thread. Process(0, 0); diff --git a/Qt/mainwindow.cpp b/Qt/mainwindow.cpp index 9c74aad70..7304c06cb 100644 --- a/Qt/mainwindow.cpp +++ b/Qt/mainwindow.cpp @@ -388,26 +388,10 @@ void SaveStateActionFinished(bool result, void *userdata) msgBox.exec(); return; } - - MainWindow* mainWindow = (MainWindow*)userdata; - - if (g_State.bEmuThreadStarted && mainWindow->GetNextState() == CORE_RUNNING) - { - if(mainWindow->GetDialogDisasm()) - mainWindow->GetDialogDisasm()->Go(); - } } void MainWindow::on_action_FileLoadStateFile_triggered() { - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - if(dialogDisasm) - { - dialogDisasm->Stop(); - } - } QFileDialog dialog(0,"Load state"); dialog.setFileMode(QFileDialog::ExistingFile); QStringList filters; @@ -425,14 +409,6 @@ void MainWindow::on_action_FileLoadStateFile_triggered() void MainWindow::on_action_FileSaveStateFile_triggered() { - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - if(dialogDisasm) - { - dialogDisasm->Stop(); - } - } QFileDialog dialog(0,"Save state"); dialog.setFileMode(QFileDialog::AnyFile); dialog.setAcceptMode(QFileDialog::AcceptSave); @@ -449,27 +425,11 @@ void MainWindow::on_action_FileSaveStateFile_triggered() void MainWindow::on_action_FileQuickloadState_triggered() { - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - if(dialogDisasm) - { - dialogDisasm->Stop(); - } - } SaveState::LoadSlot(0, SaveStateActionFinished, this); } void MainWindow::on_action_FileQuickSaveState_triggered() { - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - if(dialogDisasm) - { - dialogDisasm->Stop(); - } - } SaveState::SaveSlot(0, SaveStateActionFinished, this); } diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 30674cf9b..2a233ff03 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -308,7 +308,7 @@ namespace MainWindow if (disasmWindow[i]) SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - Sleep(100);//UGLY wait for event instead + Core_WaitInactive(); for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - Sleep(100);//UGLY wait for event instead + Core_WaitInactive(); for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - } if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); @@ -369,13 +362,6 @@ namespace MainWindow break; case ID_FILE_SAVESTATEFILE: - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - } if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn)) { SetCursor(LoadCursor(0,IDC_WAIT)); @@ -386,25 +372,11 @@ namespace MainWindow // TODO: Add UI for multiple slots case ID_FILE_QUICKLOADSTATE: - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - } SetCursor(LoadCursor(0,IDC_WAIT)); SaveState::LoadSlot(0, SaveStateActionFinished); break; case ID_FILE_QUICKSAVESTATE: - if (g_State.bEmuThreadStarted) - { - nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING; - for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_STOP, 0); - } SetCursor(LoadCursor(0,IDC_WAIT)); SaveState::SaveSlot(0, SaveStateActionFinished); break; @@ -643,7 +615,8 @@ namespace MainWindow break; case WM_CLOSE: - Sleep(100);//UGLY wait for event instead + Core_Stop(); + Core_WaitInactive(200); EmuThread_Stop(); /* @@ -896,13 +869,6 @@ namespace MainWindow if (!result) MessageBox(0, "Savestate failure. Please try again later.", "Sorry", MB_OK); SetCursor(LoadCursor(0, IDC_ARROW)); - - if (g_State.bEmuThreadStarted && nextState == CORE_RUNNING) - { - for (int i=0; iGetDlgHandle(), WM_COMMAND, IDC_GO, 0); - } } void SetNextState(CoreState state) diff --git a/native b/native index a9a067ef8..9c183fcca 160000 --- a/native +++ b/native @@ -1 +1 @@ -Subproject commit a9a067ef8473628f170dfdab1f7692b53a5f130b +Subproject commit 9c183fcca8416a34d510880d483ccf5f2ec573f4