mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
Fix/prevent crashes when MainWindow is closed before LoadFile() completes, or when it gets certain messages before TheThread completes initialization.
Fix missing ppsspp.ini loading log (only 1 unimportant line though). Fix loading ui_atlas.zim failure when [General]Browse = True is set in ppsspp.ini. Some other minor fixes as well.
This commit is contained in:
parent
ce2c18d2fe
commit
bb5fce600e
@ -101,7 +101,7 @@ void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title
|
||||
if (hTriggerEvent != NULL && hThread == NULL)
|
||||
{
|
||||
logPending = new char[LOG_PENDING_MAX];
|
||||
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) &ConsoleListener::RunThread, this, 0, NULL);
|
||||
hThread = (HANDLE)_beginthreadex(NULL, 0, &ConsoleListener::RunThread, this, 0, NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -246,9 +246,9 @@ COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
|
||||
return Ret;
|
||||
}
|
||||
|
||||
DWORD WINAPI ConsoleListener::RunThread(LPVOID lpParam)
|
||||
unsigned int WINAPI ConsoleListener::RunThread(void *lpParam)
|
||||
{
|
||||
ConsoleListener *consoleLog = (ConsoleListener *) lpParam;
|
||||
ConsoleListener *consoleLog = (ConsoleListener *)lpParam;
|
||||
consoleLog->LogWriterThread();
|
||||
return 0;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ private:
|
||||
HWND GetHwnd(void);
|
||||
HANDLE hConsole;
|
||||
|
||||
static DWORD WINAPI RunThread(LPVOID lpParam);
|
||||
static unsigned int WINAPI RunThread(void *lpParam);
|
||||
void LogWriterThread();
|
||||
void SendToThread(LogTypes::LOG_LEVELS Level, const char *Text);
|
||||
void WriteToConsole(LogTypes::LOG_LEVELS Level, const char *Text, size_t Len);
|
||||
|
@ -70,6 +70,11 @@ bool Core_IsStepping()
|
||||
return coreState == CORE_STEPPING || coreState == CORE_POWERDOWN;
|
||||
}
|
||||
|
||||
bool Core_IsActive()
|
||||
{
|
||||
return coreState == CORE_RUNNING || coreState == CORE_NEXTFRAME || coreStatePending;
|
||||
}
|
||||
|
||||
bool Core_IsInactive()
|
||||
{
|
||||
return coreState != CORE_RUNNING && coreState != CORE_NEXTFRAME && !coreStatePending;
|
||||
@ -77,7 +82,7 @@ bool Core_IsInactive()
|
||||
|
||||
void Core_WaitInactive()
|
||||
{
|
||||
while (!Core_IsInactive())
|
||||
while (Core_IsActive())
|
||||
m_hInactiveEvent.wait(m_hInactiveMutex);
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ void Core_Halt(const char *msg);
|
||||
|
||||
bool Core_IsStepping();
|
||||
|
||||
bool Core_IsActive();
|
||||
bool Core_IsInactive();
|
||||
void Core_WaitInactive();
|
||||
void Core_WaitInactive(int milliseconds);
|
||||
|
@ -97,7 +97,8 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string)
|
||||
// TODO: Check Game INI here for settings, patches and cheats, and modify coreParameter accordingly
|
||||
|
||||
std::string filename = coreParameter.fileToStart;
|
||||
if (!LoadFile(filename, error_string)) {
|
||||
if (!LoadFile(filename, error_string) || coreState == CORE_POWERDOWN)
|
||||
{
|
||||
pspFileSystem.Shutdown();
|
||||
CoreTiming::Shutdown();
|
||||
__KernelShutdown();
|
||||
|
@ -110,7 +110,7 @@ namespace DSound
|
||||
int lastPos;
|
||||
short realtimeBuffer[BUFSIZE * 2];
|
||||
|
||||
DWORD WINAPI soundThread(void *)
|
||||
unsigned int WINAPI soundThread(void *)
|
||||
{
|
||||
currentPos = 0;
|
||||
lastPos = 0;
|
||||
@ -175,8 +175,7 @@ namespace DSound
|
||||
memset(p1,0,num1);
|
||||
dsBuffer->Unlock(p1,num1,0,0);
|
||||
totalRenderedBytes = -bufferSize;
|
||||
DWORD h;
|
||||
hThread = CreateThread(0,0,soundThread,0,0,&h);
|
||||
hThread = (HANDLE)_beginthreadex(0, 0, soundThread, 0, 0, 0);
|
||||
SetThreadPriority(hThread, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||
return true;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ BOOL CDisasm::DlgProc(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
|
||||
case IDC_MEMCHECK:
|
||||
{
|
||||
bool isRunning = !Core_IsInactive();
|
||||
bool isRunning = Core_IsActive();
|
||||
if (isRunning)
|
||||
{
|
||||
SetDebugMode(true);
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "StringUtils.h"
|
||||
#include "../Globals.h"
|
||||
#include "EmuThread.h"
|
||||
#include "WndMainWindow.h"
|
||||
#include "resource.h"
|
||||
#include "../Core/Reporting.h"
|
||||
#include "../Core/MemMap.h"
|
||||
#include "../Core/Core.h"
|
||||
@ -17,34 +19,79 @@
|
||||
|
||||
#include <tchar.h>
|
||||
#include <process.h>
|
||||
#include <intrin.h>
|
||||
#pragma intrinsic(_InterlockedExchange)
|
||||
|
||||
class EmuThreadLockGuard
|
||||
{
|
||||
public:
|
||||
EmuThreadLockGuard() { emuThreadCS_.Enter(); }
|
||||
~EmuThreadLockGuard() { emuThreadCS_.Leave(); }
|
||||
private:
|
||||
static struct EmuThreadCS
|
||||
{
|
||||
EmuThreadCS() { InitializeCriticalSection(&TheCS_); }
|
||||
~EmuThreadCS() { DeleteCriticalSection(&TheCS_); }
|
||||
void Enter() { EnterCriticalSection(&TheCS_); }
|
||||
void Leave() { LeaveCriticalSection(&TheCS_); }
|
||||
CRITICAL_SECTION TheCS_;
|
||||
} emuThreadCS_;
|
||||
};
|
||||
|
||||
EmuThreadLockGuard::EmuThreadCS EmuThreadLockGuard::emuThreadCS_;
|
||||
static HANDLE emuThread;
|
||||
static long emuThreadReady;
|
||||
|
||||
enum EmuTreadStatus : long
|
||||
{
|
||||
THREAD_NONE = 0,
|
||||
THREAD_INIT,
|
||||
THREAD_CORE_LOOP,
|
||||
THREAD_SHUTDOWN,
|
||||
THREAD_END,
|
||||
};
|
||||
|
||||
HANDLE EmuThread_GetThreadHandle()
|
||||
{
|
||||
EmuThreadLockGuard lock;
|
||||
return emuThread;
|
||||
}
|
||||
|
||||
DWORD TheThread(LPVOID x);
|
||||
unsigned int WINAPI TheThread(void *);
|
||||
|
||||
void EmuThread_Start()
|
||||
{
|
||||
unsigned int i;
|
||||
emuThread = (HANDLE)_beginthreadex(0,0,(unsigned int (__stdcall *)(void *))TheThread,(LPVOID)0,0,&i);
|
||||
EmuThreadLockGuard lock;
|
||||
emuThread = (HANDLE)_beginthreadex(0, 0, &TheThread, 0, 0, 0);
|
||||
}
|
||||
|
||||
void EmuThread_Stop()
|
||||
{
|
||||
// DSound_UpdateSound();
|
||||
Core_Stop();
|
||||
if (WAIT_TIMEOUT == WaitForSingleObject(EmuThread_GetThreadHandle(),300))
|
||||
Core_WaitInactive(800);
|
||||
if (WAIT_TIMEOUT == WaitForSingleObject(emuThread, 800))
|
||||
{
|
||||
//MessageBox(0,"Wait for emuthread timed out, please alert the developer to possible deadlock or infinite loop in emuthread :(.",0,0);
|
||||
MessageBox(MainWindow::GetHWND(),"Wait for emuthread timed out! :(\n"
|
||||
"please alert the developer to possible deadlock or infinite loop in emuthread!", 0, 0);
|
||||
}
|
||||
{
|
||||
EmuThreadLockGuard lock;
|
||||
CloseHandle(emuThread);
|
||||
emuThread = 0;
|
||||
}
|
||||
host->UpdateUI();
|
||||
}
|
||||
|
||||
DWORD TheThread(LPVOID x) {
|
||||
bool EmuThread_Ready()
|
||||
{
|
||||
return emuThreadReady == THREAD_CORE_LOOP;
|
||||
}
|
||||
|
||||
unsigned int WINAPI TheThread(void *)
|
||||
{
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_INIT);
|
||||
|
||||
setCurrentThreadName("EmuThread");
|
||||
|
||||
std::string memstick, flash0;
|
||||
@ -75,20 +122,36 @@ DWORD TheThread(LPVOID x) {
|
||||
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);
|
||||
//MainWindow::BrowseAndBoot("");
|
||||
}
|
||||
|
||||
Core_EnableStepping(FALSE);
|
||||
|
||||
Core_Run();
|
||||
|
||||
shutdown:
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN);
|
||||
|
||||
host = nativeHost;
|
||||
NativeShutdownGraphics();
|
||||
NativeShutdown();
|
||||
host = oldHost;
|
||||
|
||||
host->ShutdownGL();
|
||||
|
||||
_InterlockedExchange(&emuThreadReady, THREAD_END);
|
||||
|
||||
//The CPU should return when a game is stopped and cleanup should be done here,
|
||||
//so we can restart the plugins (or load new ones) for the next game
|
||||
_endthreadex(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,22 @@
|
||||
// Copyright (c) 2013- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
void EmuThread_Start();
|
||||
void EmuThread_Stop();
|
||||
void EmuThread_Stop();
|
||||
bool EmuThread_Ready();
|
||||
|
@ -214,18 +214,21 @@ namespace MainWindow
|
||||
if (zoom < 1) zoom = 1;
|
||||
if (zoom > 4) zoom = 4;
|
||||
|
||||
RECT rc,rcOrig;
|
||||
RECT rc, rcOrig;
|
||||
GetWindowRectAtZoom(zoom, rcOrig, rc);
|
||||
|
||||
u32 style = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
hwndMain = CreateWindowEx(0,szWindowClass, "", style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL);
|
||||
SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0);
|
||||
SetPlaying(0);
|
||||
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance, NULL);
|
||||
if (!hwndMain)
|
||||
return FALSE;
|
||||
|
||||
hwndDisplay = CreateWindowEx(0, szDisplayClass, TEXT(""), WS_CHILD | WS_VISIBLE,
|
||||
rcOrig.left, rcOrig.top, rcOrig.right - rcOrig.left, rcOrig.bottom - rcOrig.top, hwndMain, 0, hInstance, 0);
|
||||
if (!hwndDisplay)
|
||||
return FALSE;
|
||||
|
||||
menu = GetMenu(hwndMain);
|
||||
#ifdef FINAL
|
||||
RemoveMenu(menu,2,MF_BYPOSITION);
|
||||
@ -241,20 +244,22 @@ namespace MainWindow
|
||||
{
|
||||
SetMenuInfo(GetSubMenu(menu,i),&info);
|
||||
}
|
||||
UpdateMenus();
|
||||
|
||||
hwndDisplay = CreateWindowEx(0,szDisplayClass,TEXT(""),
|
||||
WS_CHILD|WS_VISIBLE,
|
||||
0,0,/*rcOrig.left,rcOrig.top,*/rcOrig.right-rcOrig.left,rcOrig.bottom-rcOrig.top,hwndMain,0,hInstance,0);
|
||||
|
||||
ShowWindow(hwndMain, nCmdShow);
|
||||
//accept dragged files
|
||||
DragAcceptFiles(hwndMain, TRUE);
|
||||
|
||||
SetTimer(hwndMain, TIMER_CURSORUPDATE, CURSORUPDATE_INTERVAL_MS, 0);
|
||||
|
||||
Update();
|
||||
SetPlaying(0);
|
||||
|
||||
ShowWindow(hwndMain, nCmdShow);
|
||||
|
||||
#if ENABLE_TOUCH
|
||||
RegisterTouchWindow(hwndDisplay, TWF_WANTPALM);
|
||||
#endif
|
||||
|
||||
SetFocus(hwndMain);
|
||||
SetFocus(hwndDisplay);
|
||||
|
||||
return TRUE;
|
||||
@ -429,6 +434,8 @@ namespace MainWindow
|
||||
|
||||
case WM_COMMAND:
|
||||
{
|
||||
if (!EmuThread_Ready())
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
I18NCategory *g = GetI18NCategory("Graphics");
|
||||
|
||||
wmId = LOWORD(wParam);
|
||||
@ -735,6 +742,9 @@ namespace MainWindow
|
||||
|
||||
case WM_DROPFILES:
|
||||
{
|
||||
if (!EmuThread_Ready())
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
|
||||
HDROP hdrop = (HDROP)wParam;
|
||||
int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0);
|
||||
if (count != 1)
|
||||
@ -760,21 +770,14 @@ namespace MainWindow
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
Core_Stop();
|
||||
Core_WaitInactive(200);
|
||||
/*
|
||||
if (g_Config.bConfirmOnQuit && __KernelIsRunning())
|
||||
if (IDYES != MessageBox(hwndMain, "A game is in progress. Are you sure you want to exit?",
|
||||
"Are you sure?", MB_YESNO | MB_ICONQUESTION))
|
||||
return 0;
|
||||
//*/
|
||||
EmuThread_Stop();
|
||||
|
||||
/*
|
||||
if (g_Config.bConfirmOnQuit && CCore::IsRunning())
|
||||
{
|
||||
if (IDNO==MessageBox(hwndMain,"A game is in progress. Are you sure you want to exit?","Are you sure?",MB_YESNO|MB_ICONQUESTION))
|
||||
return 1;//or 1?
|
||||
else
|
||||
return DefWindowProc(hWnd,message,wParam,lParam);
|
||||
break;
|
||||
}
|
||||
else
|
||||
*/
|
||||
return DefWindowProc(hWnd,message,wParam,lParam);
|
||||
|
||||
case WM_DESTROY:
|
||||
|
@ -64,9 +64,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
hideLog = false;
|
||||
#endif
|
||||
|
||||
LogManager::Init();
|
||||
LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console");
|
||||
LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
|
||||
|
||||
g_Config.Load();
|
||||
VFSRegister("", new DirectoryAssetReader("assets/"));
|
||||
VFSRegister("", new DirectoryAssetReader(""));
|
||||
|
||||
// The rest is handled in NativeInit().
|
||||
for (int i = 1; i < __argc; ++i)
|
||||
@ -89,6 +91,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
}
|
||||
}
|
||||
|
||||
VFSRegister("", new DirectoryAssetReader("assets/"));
|
||||
VFSRegister("", new DirectoryAssetReader(""));
|
||||
|
||||
//Windows, API init stuff
|
||||
INITCOMMONCONTROLSEX comm;
|
||||
comm.dwSize = sizeof(comm);
|
||||
@ -97,15 +102,13 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
timeBeginPeriod(1);
|
||||
MainWindow::Init(_hInstance);
|
||||
|
||||
HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
|
||||
g_hPopupMenus = LoadMenu(_hInstance, (LPCSTR)IDR_POPUPMENUS);
|
||||
|
||||
MainWindow::Show(_hInstance, iCmdShow);
|
||||
host = new WindowsHost(MainWindow::GetHWND(), MainWindow::GetDisplayHWND());
|
||||
|
||||
HWND hwndMain = MainWindow::GetHWND();
|
||||
HMENU menu = GetMenu(hwndMain);
|
||||
|
||||
HWND hwndDisplay = MainWindow::GetDisplayHWND();
|
||||
|
||||
//initialize custom controls
|
||||
CtrlDisAsmView::init();
|
||||
CtrlMemView::init();
|
||||
@ -114,25 +117,15 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin
|
||||
DialogManager::AddDlg(memoryWindow[0] = new CMemoryDlg(_hInstance, hwndMain, currentDebugMIPS));
|
||||
DialogManager::AddDlg(vfpudlg = new CVFPUDlg(_hInstance, hwndMain, currentDebugMIPS));
|
||||
|
||||
MainWindow::Update();
|
||||
MainWindow::UpdateMenus();
|
||||
|
||||
LogManager::Init();
|
||||
LogManager::GetInstance()->GetConsoleListener()->Open(hideLog, 150, 120, "PPSSPP Debug Console");
|
||||
LogManager::GetInstance()->SetLogLevel(LogTypes::G3D, LogTypes::LERROR);
|
||||
host = new WindowsHost(hwndMain, hwndDisplay);
|
||||
|
||||
// Emu thread is always running!
|
||||
EmuThread_Start();
|
||||
|
||||
if (g_Config.bBrowse)
|
||||
MainWindow::BrowseAndBoot("");
|
||||
|
||||
if (!hideLog)
|
||||
SetForegroundWindow(hwndMain);
|
||||
HACCEL hAccelTable = LoadAccelerators(_hInstance, (LPCTSTR)IDR_ACCELS);
|
||||
|
||||
//so.. we're at the message pump of the GUI thread
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, NULL, 0, 0)) //while no quit
|
||||
for (MSG msg; GetMessage(&msg, NULL, 0, 0); ) // for no quit
|
||||
{
|
||||
//DSound_UpdateSound();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user