ppsspp/Windows/EmuThread.cpp

185 lines
4.3 KiB
C++
Raw Normal View History

2012-11-01 16:19:01 +01:00
// NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
2013-03-29 18:50:08 +01:00
#include "base/timeutil.h"
#include "base/NativeApp.h"
#include "base/mutex.h"
#include "util/text/utf8.h"
#include "Common/Log.h"
#include "Common/StringUtils.h"
2012-11-01 16:19:01 +01:00
#include "../Globals.h"
#include "Windows/EmuThread.h"
#include "Windows/WndMainWindow.h"
#include "Windows/resource.h"
#include "Core/Reporting.h"
#include "Core/MemMap.h"
#include "Core/Core.h"
#include "Core/Host.h"
#include "Core/System.h"
#include "Core/Config.h"
#include "thread/threadutil.h"
2012-11-01 16:19:01 +01:00
#include <tchar.h>
#include <process.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedExchange)
static recursive_mutex emuThreadLock;
2012-11-01 16:19:01 +01:00
static HANDLE emuThread;
static volatile long emuThreadReady;
extern std::vector<std::wstring> GetWideCmdLine();
enum EmuThreadStatus : long
{
THREAD_NONE = 0,
THREAD_INIT,
THREAD_CORE_LOOP,
THREAD_SHUTDOWN,
THREAD_END,
};
2012-11-01 16:19:01 +01:00
HANDLE EmuThread_GetThreadHandle()
{
lock_guard guard(emuThreadLock);
2012-11-01 16:19:01 +01:00
return emuThread;
}
unsigned int WINAPI TheThread(void *);
2012-11-01 16:19:01 +01:00
2013-03-29 18:50:08 +01:00
void EmuThread_Start()
2012-11-01 16:19:01 +01:00
{
lock_guard guard(emuThreadLock);
emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0);
2012-11-01 16:19:01 +01:00
}
void EmuThread_Stop()
{
2013-08-13 08:03:13 -07:00
// Already stopped?
{
lock_guard guard(emuThreadLock);
2014-02-09 17:35:43 -08:00
if (emuThread == NULL || emuThreadReady == THREAD_END)
return;
}
2013-08-13 08:03:13 -07:00
UpdateUIState(UISTATE_EXIT);
2012-11-01 16:19:01 +01:00
Core_Stop();
Core_WaitInactive(800);
if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800))
{
_dbg_assert_msg_(COMMON, false, "Wait for EmuThread timed out.");
}
2012-11-01 16:19:01 +01:00
{
lock_guard guard(emuThreadLock);
CloseHandle(emuThread);
emuThread = 0;
2012-11-01 16:19:01 +01:00
}
host->UpdateUI();
}
bool EmuThread_Ready()
{
return emuThreadReady == THREAD_CORE_LOOP;
}
unsigned int WINAPI TheThread(void *)
{
_InterlockedExchange(&emuThreadReady, THREAD_INIT);
setCurrentThreadName("Emu"); // And graphics...
2012-11-01 16:19:01 +01:00
2013-03-29 18:50:08 +01:00
// Native overwrites host. Can't allow that.
Host *oldHost = host;
// Convert the command-line arguments to Unicode, then to proper UTF-8
// (the benefit being that we don't have to pollute the UI project with win32 ifdefs and lots of Convert<whatever>To<whatever>).
// This avoids issues with PPSSPP inadvertently destroying paths with Unicode glyphs
// (using the ANSI args resulted in Japanese/Chinese glyphs being turned into question marks, at least for me..).
// -TheDax
std::vector<std::wstring> wideArgs = GetWideCmdLine();
std::vector<std::string> argsUTF8;
for (auto& string : wideArgs)
{
argsUTF8.push_back(ConvertWStringToUTF8(string));
}
std::vector<const char *> args;
for (auto& string: argsUTF8)
{
args.push_back(string.c_str());
}
NativeInit(static_cast<int>(args.size()), &args[0], "1234", "1234", "1234");
2013-03-29 18:50:08 +01:00
Host *nativeHost = host;
host = oldHost;
2012-11-01 16:19:01 +01:00
host->UpdateUI();
//Check Colour depth
HDC dc = GetDC(NULL);
u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL);
ReleaseDC(NULL, dc);
if (colour_depth != 32){
MessageBox(0, L"Please switch your display to 32-bit colour mode", L"OpenGL Error", MB_OK);
ExitProcess(1);
}
std::string error_string;
if (!host->InitGL(&error_string)) {
2014-08-17 16:07:14 +02:00
Reporting::ReportMessage("Graphics init error: %s", error_string.c_str());
std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str());
MessageBox(0, ConvertUTF8ToWString(full_error).c_str(), L"OpenGL Error", MB_OK | MB_ICONERROR);
ERROR_LOG(BOOT, full_error.c_str());
// No safe way out without OpenGL.
ExitProcess(1);
}
2012-11-01 16:19:01 +01:00
2013-03-29 18:50:08 +01:00
NativeInitGraphics();
NativeResized();
2012-11-01 16:19:01 +01:00
INFO_LOG(BOOT, "Done.");
_dbg_update_();
if (coreState == CORE_POWERDOWN) {
INFO_LOG(BOOT, "Exit before core loop.");
goto shutdown;
}
_InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP);
if (g_Config.bBrowse)
PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0);
2013-03-29 18:50:08 +01:00
Core_EnableStepping(FALSE);
while (GetUIState() != UISTATE_EXIT)
{
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
// This way they can load a new game.
if (!Core_IsActive())
UpdateUIState(UISTATE_MENU);
Core_Run();
}
2012-11-01 16:19:01 +01:00
2012-11-05 13:42:33 +01:00
shutdown:
_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);
2013-03-29 18:50:08 +01:00
NativeShutdownGraphics();
host->ShutdownSound();
host = nativeHost;
2013-03-29 18:50:08 +01:00
NativeShutdown();
host = oldHost;
2012-11-01 16:19:01 +01:00
host->ShutdownGL();
_InterlockedExchange(&emuThreadReady, THREAD_END);
2012-11-01 16:19:01 +01:00
return 0;
}