// Called from GUI thread void Stop() // - Hammertime! { if (GetState() == CORE_STOPPING) return; const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; s_is_stopping = true; g_video_backend->EmuStateChange(EMUSTATE_CHANGE_STOP); INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutting down ----"); // Stop the CPU INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stop CPU").c_str()); PowerPC::Stop(); // Kick it if it's waiting (code stepping wait loop) CCPU::StepOpcode(); if (_CoreParameter.bCPUThread) { // Video_EnterLoop() should now exit so that EmuThread() // will continue concurrently with the rest of the commands // in this function. We no longer rely on Postmessage. INFO_LOG(CONSOLE, "%s", StopMessage(true, "Wait for Video Loop to exit ...").c_str()); g_video_backend->Video_ExitLoop(); } }
// Called from GUI thread void Stop() // - Hammertime! { if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN) { if (g_EmuThread.joinable()) g_EmuThread.join(); return; } const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; g_bStopping = true; g_video_backend->EmuStateChange(EMUSTATE_CHANGE_STOP); INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutting down ----"); // Stop the CPU INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stop CPU").c_str()); PowerPC::Stop(); // Kick it if it's waiting (code stepping wait loop) CCPU::StepOpcode(); if (_CoreParameter.bCPUThread) { // Video_EnterLoop() should now exit so that EmuThread() // will continue concurrently with the rest of the commands // in this function. We no longer rely on Postmessage. INFO_LOG(CONSOLE, "%s", StopMessage(true, "Wait for Video Loop to exit ...").c_str()); g_video_backend->Video_ExitLoop(); } INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); g_EmuThread.join(); // Wait for emuthread to close. INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str()); #ifdef _WIN32 EmuWindow::Close(); #endif // Clear on screen messages that haven't expired g_video_backend->Video_ClearMessages(); // Close the trace file Core::StopTrace(); // Reload sysconf file in order to see changes committed during emulation if (_CoreParameter.bWii) SConfig::GetInstance().m_SYSCONF->Reload(); INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutdown complete ----"); Movie::Shutdown(); g_bStopping = false; }
// Called from GUI thread void Stop() // - Hammertime! { if (GetState() == CORE_STOPPING) return; const SConfig& _CoreParameter = SConfig::GetInstance(); s_is_stopping = true; // Dump left over jobs HostDispatchJobs(); Fifo::EmulatorState(false); INFO_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutting down ----"); // Stop the CPU INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stop CPU").c_str()); CPU::Stop(); if (_CoreParameter.bCPUThread) { // Video_EnterLoop() should now exit so that EmuThread() // will continue concurrently with the rest of the commands // in this function. We no longer rely on Postmessage. INFO_LOG(CONSOLE, "%s", StopMessage(true, "Wait for Video Loop to exit ...").c_str()); g_video_backend->Video_ExitLoop(); } #if defined(__LIBUSB__) || defined(_WIN32) GCAdapter::ResetRumble(); #endif #ifdef USE_MEMORYWATCHER MemoryWatcher::Shutdown(); #endif }
// Initialize and create emulation thread // Call browser: Init():s_emu_thread(). // See the BootManager.cpp file description for a complete call schedule. void EmuThread() { const SCoreStartupParameter& core_parameter = SConfig::GetInstance().m_LocalCoreStartupParameter; Common::SetCurrentThreadName("Emuthread - Starting"); if (SConfig::GetInstance().m_OCEnable) DisplayMessage("WARNING: running at non-native CPU clock! Game may not be stable.", 8000); DisplayMessage(cpu_info.brand_string, 8000); DisplayMessage(cpu_info.Summarize(), 8000); DisplayMessage(core_parameter.m_strFilename, 3000); Movie::Init(); HW::Init(); if (!g_video_backend->Initialize(s_window_handle)) { PanicAlert("Failed to initialize video backend!"); Host_Message(WM_USER_STOP); return; } OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000); if (cpu_info.HTT) SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread = cpu_info.num_cores > 4; else SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread = cpu_info.num_cores > 2; if (!DSP::GetDSPEmulator()->Initialize(core_parameter.bWii, core_parameter.bDSPThread)) { HW::Shutdown(); g_video_backend->Shutdown(); PanicAlert("Failed to initialize DSP emulator!"); Host_Message(WM_USER_STOP); return; } Keyboard::Initialize(s_window_handle); Pad::Initialize(s_window_handle); // Load and Init Wiimotes - only if we are booting in Wii mode if (core_parameter.bWii) { Wiimote::Initialize(s_window_handle, !s_state_filename.empty()); // Activate Wiimotes which don't have source set to "None" for (unsigned int i = 0; i != MAX_BBMOTES; ++i) if (g_wiimote_sources[i]) GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true); } AudioCommon::InitSoundStream(); // The hardware is initialized. s_hardware_initialized = true; // Boot to pause or not Core::SetState(core_parameter.bBootToPause ? Core::CORE_PAUSE : Core::CORE_RUN); // Load GCM/DOL/ELF whatever ... we boot with the interpreter core PowerPC::SetMode(PowerPC::MODE_INTERPRETER); CBoot::BootUp(); // Setup our core, but can't use dynarec if we are compare server if (core_parameter.iCPUCore != SCoreStartupParameter::CORE_INTERPRETER && (!core_parameter.bRunCompareServer || core_parameter.bRunCompareClient)) { PowerPC::SetMode(PowerPC::MODE_JIT); } else { PowerPC::SetMode(PowerPC::MODE_INTERPRETER); } // Update the window again because all stuff is initialized Host_UpdateDisasmDialog(); Host_UpdateMainFrame(); // Determine the CPU thread function void (*cpuThreadFunc)(void); if (core_parameter.m_BootType == SCoreStartupParameter::BOOT_DFF) cpuThreadFunc = FifoPlayerThread; else cpuThreadFunc = CpuThread; // ENTER THE VIDEO THREAD LOOP if (core_parameter.bCPUThread) { // This thread, after creating the EmuWindow, spawns a CPU // thread, and then takes over and becomes the video thread Common::SetCurrentThreadName("Video thread"); g_video_backend->Video_Prepare(); // Spawn the CPU thread s_cpu_thread = std::thread(cpuThreadFunc); // become the GPU thread g_video_backend->Video_EnterLoop(); // We have now exited the Video Loop INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str()); } else // SingleCore mode { // The spawned CPU Thread also does the graphics. // The EmuThread is thus an idle thread, which sleeps while // waiting for the program to terminate. Without this extra // thread, the video backend window hangs in single core mode // because no one is pumping messages. Common::SetCurrentThreadName("Emuthread - Idle"); // Spawn the CPU+GPU thread s_cpu_thread = std::thread(cpuThreadFunc); while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) { g_video_backend->PeekMessages(); Common::SleepCurrentThread(20); } } INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping Emu thread ...").c_str()); // Wait for s_cpu_thread to exit INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str()); #ifdef USE_GDBSTUB INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str()); gdb_deinit(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str()); #endif s_cpu_thread.join(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str()); if (core_parameter.bCPUThread) g_video_backend->Video_Cleanup(); VolumeHandler::EjectVolume(); FileMon::Close(); // Stop audio thread - Actually this does nothing when using HLE // emulation, but stops the DSP Interpreter when using LLE emulation. DSP::GetDSPEmulator()->DSP_StopSoundStream(); // We must set up this flag before executing HW::Shutdown() s_hardware_initialized = false; INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str()); HW::Shutdown(); INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str()); Wiimote::Shutdown(); Keyboard::Shutdown(); Pad::Shutdown(); g_video_backend->Shutdown(); AudioCommon::ShutdownSoundStream(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "Main Emu thread stopped").c_str()); // Clear on screen messages that haven't expired g_video_backend->Video_ClearMessages(); // Reload sysconf file in order to see changes committed during emulation if (core_parameter.bWii) SConfig::GetInstance().m_SYSCONF->Reload(); INFO_LOG(CONSOLE, "Stop [Video Thread]\t\t---- Shutdown complete ----"); Movie::Shutdown(); PatchEngine::Shutdown(); s_is_stopping = false; if (s_on_stopped_callback) s_on_stopped_callback(); }
void CFullScreenFrame::SetupInput() { INPUTENGPARAMS inputParams; KEYBIND binding; CHashString kbName(_T("GDS_kb")); CHashString inputManager(_T("CInputManager")); CHashString StopMessage(_T("StopPlaying")); CHashString MoveForward(_T("CamMoveForward")); CHashString MoveBackward(_T("CamMoveBackward")); CHashString StrafeLeft(_T("CamStrafeLeft")); CHashString StrafeRight(_T("CamStrafeRight")); // create the input manager m_ToolBox->CreateComponent(&CHashString(_T("CInputManager")), 0); // start the input manager HMODULE mod = GetModuleHandle(NULL); inputParams.hMod = mod; inputParams.hWnd = GetSafeHwnd(); inputParams.mouseImmediate = true; inputParams.mouseExclusive = false; inputParams.mouseFG = true; inputParams.kbImmediate = true; inputParams.kbExclusive = false; inputParams.kbFG = true; static DWORD msgHash_Begin = CHashString(_T("Begin")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_Begin, sizeof(INPUTENGPARAMS), &inputParams, NULL, &inputManager); static DWORD msgHash_Start = CHashString(_T("Start")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_Start, 0, NULL, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_ESC;//0x1; binding.m_MessageID = StopMessage.GetUniqueID(); binding.m_bHitOnce = true; static DWORD msgHash_SetKeyBinding = CHashString(_T("SetKeyBinding")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_LEFT; binding.m_MessageID = StrafeLeft.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_RIGHT; binding.m_MessageID = StrafeRight.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_UP; binding.m_MessageID = MoveForward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_DOWN; binding.m_MessageID = MoveBackward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_A; binding.m_MessageID = StrafeLeft.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_D; binding.m_MessageID = StrafeRight.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_W; binding.m_MessageID = MoveForward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); CHashString reloadshaders(_T("ReloadAllShaders")); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_S; binding.m_MessageID = MoveBackward.GetUniqueID(); binding.m_bHitOnce = false; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); binding.m_kbNameID = kbName.GetUniqueID(); binding.m_KeyID = EEK_Q; binding.m_MessageID = reloadshaders.GetUniqueID(); binding.m_bHitOnce = true; m_ToolBox->SendMessage(msgHash_SetKeyBinding, sizeof(KEYBIND), &binding, NULL, &inputManager); static DWORD msgHash_SetActiveKeyBinding = CHashString(_T("SetActiveKeyBinding")).GetUniqueID(); m_ToolBox->SendMessage(msgHash_SetActiveKeyBinding, sizeof(DWORD*), &binding.m_kbNameID, &inputManager); }
// Initalize and create emulation thread // Call browser: Init():g_EmuThread(). // See the BootManager.cpp file description for a complete call schedule. void EmuThread() { const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter; Common::SetCurrentThreadName("Emuthread - Starting"); DisplayMessage(cpu_info.brand_string, 8000); DisplayMessage(cpu_info.Summarize(), 8000); DisplayMessage(_CoreParameter.m_strFilename, 3000); if (cpu_info.IsUnsafe() && (NetPlay::IsNetPlayRunning() || Movie::IsRecordingInput() || Movie::IsPlayingInput())) { PanicAlertT("Warning: Netplay/movies will desync because your CPU does not support DAZ and Dolphin does not emulate it anymore."); } Movie::Init(); HW::Init(); if (!g_video_backend->Initialize(g_pWindowHandle)) { PanicAlert("Failed to initialize video backend!"); Host_Message(WM_USER_STOP); return; } OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000); if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle, _CoreParameter.bWii, _CoreParameter.bDSPThread)) { HW::Shutdown(); g_video_backend->Shutdown(); PanicAlert("Failed to initialize DSP emulator!"); Host_Message(WM_USER_STOP); return; } Pad::Initialize(g_pWindowHandle); // Load and Init Wiimotes - only if we are booting in wii mode if (g_CoreStartupParameter.bWii) { Wiimote::Initialize(g_pWindowHandle, !g_stateFileName.empty()); // Activate wiimotes which don't have source set to "None" for (unsigned int i = 0; i != MAX_BBMOTES; ++i) if (g_wiimote_sources[i]) GetUsbPointer()->AccessWiiMote(i | 0x100)->Activate(true); } AudioCommon::InitSoundStream(g_pWindowHandle); // The hardware is initialized. g_bHwInit = true; // Boot to pause or not Core::SetState(_CoreParameter.bBootToPause ? Core::CORE_PAUSE : Core::CORE_RUN); // Load GCM/DOL/ELF whatever ... we boot with the interpreter core PowerPC::SetMode(PowerPC::MODE_INTERPRETER); CBoot::BootUp(); // Setup our core, but can't use dynarec if we are compare server if (_CoreParameter.iCPUCore && (!_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient)) PowerPC::SetMode(PowerPC::MODE_JIT); else PowerPC::SetMode(PowerPC::MODE_INTERPRETER); // Update the window again because all stuff is initialized Host_UpdateDisasmDialog(); Host_UpdateMainFrame(); // Determine the cpu thread function void (*cpuThreadFunc)(void); if (_CoreParameter.m_BootType == SCoreStartupParameter::BOOT_DFF) cpuThreadFunc = FifoPlayerThread; else cpuThreadFunc = CpuThread; // ENTER THE VIDEO THREAD LOOP if (_CoreParameter.bCPUThread) { // This thread, after creating the EmuWindow, spawns a CPU // thread, and then takes over and becomes the video thread Common::SetCurrentThreadName("Video thread"); g_video_backend->Video_Prepare(); // Spawn the CPU thread g_cpu_thread = std::thread(cpuThreadFunc); // become the GPU thread g_video_backend->Video_EnterLoop(); // We have now exited the Video Loop INFO_LOG(CONSOLE, "%s", StopMessage(false, "Video Loop Ended").c_str()); } else // SingleCore mode { // The spawned CPU Thread also does the graphics. // The EmuThread is thus an idle thread, which sleeps while // waiting for the program to terminate. Without this extra // thread, the video backend window hangs in single core mode // because noone is pumping messages. Common::SetCurrentThreadName("Emuthread - Idle"); // Spawn the CPU+GPU thread g_cpu_thread = std::thread(cpuThreadFunc); while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) { g_video_backend->PeekMessages(); Common::SleepCurrentThread(20); } } // Wait for g_cpu_thread to exit INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping CPU-GPU thread ...").c_str()); #ifdef USE_GDBSTUB INFO_LOG(CONSOLE, "%s", StopMessage(true, "Stopping GDB ...").c_str()); gdb_deinit(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "GDB stopped.").c_str()); #endif g_cpu_thread.join(); INFO_LOG(CONSOLE, "%s", StopMessage(true, "CPU thread stopped.").c_str()); if (_CoreParameter.bCPUThread) g_video_backend->Video_Cleanup(); VolumeHandler::EjectVolume(); FileMon::Close(); // Stop audio thread - Actually this does nothing when using HLE // emulation, but stops the DSP Interpreter when using LLE emulation. DSP::GetDSPEmulator()->DSP_StopSoundStream(); // We must set up this flag before executing HW::Shutdown() g_bHwInit = false; INFO_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down HW").c_str()); HW::Shutdown(); INFO_LOG(CONSOLE, "%s", StopMessage(false, "HW shutdown").c_str()); Pad::Shutdown(); Wiimote::Shutdown(); g_video_backend->Shutdown(); AudioCommon::ShutdownSoundStream(); }