// 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();
	}
}
Esempio n. 2
0
// 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;
}
Esempio n. 3
0
// 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);
}
Esempio n. 6
0
// 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();
}