2012-11-01 16:19:01 +01:00
// Copyright (c) 2012- 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
2012-11-04 23:01:49 +01:00
// the Free Software Foundation, version 2.0 or later versions.
2012-11-01 16:19:01 +01:00
// 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/.
2018-03-23 22:54:12 +01:00
# include "stdafx.h"
2015-12-25 19:14:05 -08:00
# include <algorithm>
2016-12-05 16:51:28 +01:00
# include <cmath>
2020-03-08 18:59:17 -07:00
# include <functional>
2014-02-13 15:57:36 +01:00
2013-07-28 21:01:49 -07:00
# include "Common/CommonWindows.h"
2020-10-04 20:48:47 +02:00
# include "Common/File/FileUtil.h"
2017-02-14 10:33:42 +01:00
# include "Common/OSVersion.h"
2020-10-04 23:24:14 +02:00
# include "Common/GPU/Vulkan/VulkanLoader.h"
2019-05-10 23:25:57 +02:00
# include "ppsspp_config.h"
2017-02-14 10:33:42 +01:00
2016-12-05 16:51:28 +01:00
# include <Wbemidl.h>
# include <shellapi.h>
2019-05-21 23:22:56 +02:00
# include <ShlObj.h>
2016-12-05 16:51:28 +01:00
# include <mmsystem.h>
2012-11-01 16:19:01 +01:00
2020-10-04 10:10:55 +02:00
# include "Common/System/Display.h"
2020-10-04 10:30:18 +02:00
# include "Common/System/NativeApp.h"
# include "Common/System/System.h"
2022-09-19 08:30:57 -07:00
# include "Common/File/FileUtil.h"
2020-10-04 00:25:21 +02:00
# include "Common/File/VFS/VFS.h"
2023-03-06 15:30:39 +01:00
# include "Common/File/VFS/DirectoryReader.h"
2020-10-01 13:05:04 +02:00
# include "Common/Data/Text/I18n.h"
2020-10-04 10:04:01 +02:00
# include "Common/Profiler/Profiler.h"
2020-10-01 09:27:25 +02:00
# include "Common/Thread/ThreadUtil.h"
2020-10-01 13:05:04 +02:00
# include "Common/Data/Encoding/Utf8.h"
2020-10-04 20:48:47 +02:00
# include "Common/Net/Resolve.h"
2020-05-04 17:33:39 +02:00
# include "W32Util/DarkMode.h"
2012-11-01 16:19:01 +01:00
2013-07-28 21:01:49 -07:00
# include "Core/Config.h"
2018-06-16 18:42:31 -07:00
# include "Core/ConfigValues.h"
2013-07-28 21:01:49 -07:00
# include "Core/SaveState.h"
# include "Windows/EmuThread.h"
2017-06-27 11:46:10 +02:00
# include "Windows/WindowsAudio.h"
2013-01-08 17:03:17 +01:00
# include "ext/disarm.h"
2012-11-01 16:19:01 +01:00
2013-07-28 21:01:49 -07:00
# include "Common/LogManager.h"
# include "Common/ConsoleListener.h"
2020-09-29 12:19:22 +02:00
# include "Common/StringUtils.h"
2012-11-01 16:19:01 +01:00
# include "Commctrl.h"
2015-10-04 12:24:59 +02:00
# include "UI/GameInfoCache.h"
2012-11-01 16:19:01 +01:00
# include "Windows/resource.h"
2015-09-19 13:14:05 +02:00
# include "Windows/MainWindow.h"
2013-09-22 10:27:09 -07:00
# include "Windows/Debugger/Debugger_Disasm.h"
2012-11-01 16:19:01 +01:00
# include "Windows/Debugger/Debugger_MemoryDlg.h"
# include "Windows/Debugger/Debugger_VFPUDlg.h"
2019-05-10 23:25:57 +02:00
# if PPSSPP_API(ANY_GL)
2013-09-22 11:03:29 -07:00
# include "Windows/GEDebugger/GEDebugger.h"
2019-05-04 06:06:50 +08:00
# endif
2021-10-07 19:53:40 -07:00
# include "Windows/W32Util/ContextMenu.h"
2012-11-01 16:19:01 +01:00
# include "Windows/W32Util/DialogManager.h"
2019-02-17 08:03:10 -08:00
# include "Windows/W32Util/ShellUtil.h"
2012-11-01 16:19:01 +01:00
# include "Windows/Debugger/CtrlDisAsmView.h"
# include "Windows/Debugger/CtrlMemView.h"
# include "Windows/Debugger/CtrlRegisterList.h"
2013-12-08 20:16:18 +10:00
# include "Windows/InputBox.h"
2012-11-01 16:19:01 +01:00
# include "Windows/WindowsHost.h"
# include "Windows/main.h"
2016-04-21 23:03:08 -04:00
2017-08-28 13:45:04 +02:00
// Nvidia OpenGL drivers >= v302 will check if the application exports a global
2014-03-03 11:26:27 -05:00
// variable named NvOptimusEnablement to know if it should run the app in high
// performance graphics mode or using the IGP.
extern " C " {
__declspec ( dllexport ) DWORD NvOptimusEnablement = 1 ;
}
2018-04-15 08:41:02 +02:00
// Also on AMD PowerExpress: https://community.amd.com/thread/169965
extern " C " {
__declspec ( dllexport ) int AmdPowerXpressRequestHighPerformance = 1 ;
}
2019-05-10 23:25:57 +02:00
# if PPSSPP_API(ANY_GL)
2020-09-24 00:17:31 +02:00
CGEDebugger * geDebuggerWindow = nullptr ;
2019-05-04 06:06:50 +08:00
# endif
2018-04-15 08:41:02 +02:00
2020-09-24 00:17:31 +02:00
CDisasm * disasmWindow = nullptr ;
CMemoryDlg * memoryWindow = nullptr ;
2021-11-13 22:24:30 +01:00
CVFPUDlg * vfpudlg = nullptr ;
2012-11-01 16:19:01 +01:00
2013-09-04 12:07:42 +02:00
static std : : string langRegion ;
2013-10-09 17:17:28 -04:00
static std : : string osName ;
2014-07-31 01:21:37 -04:00
static std : : string gpuDriverVersion ;
2013-09-04 12:07:42 +02:00
2020-05-09 13:52:04 -07:00
static std : : string restartArgs ;
2017-08-31 17:13:18 +02:00
int g_activeWindow = 0 ;
2021-02-18 07:27:28 -08:00
static std : : thread inputBoxThread ;
static bool inputBoxRunning = false ;
2019-05-21 23:22:56 +02:00
void OpenDirectory ( const char * path ) {
2022-09-19 08:30:57 -07:00
// SHParseDisplayName can't handle relative paths, so normalize first.
std : : string resolved = ReplaceAll ( File : : ResolvePath ( path ) , " / " , " \\ " ) ;
2022-12-10 21:09:50 -08:00
SFGAOF flags { } ;
2021-10-09 15:58:49 -07:00
PIDLIST_ABSOLUTE pidl = nullptr ;
2022-09-19 08:30:57 -07:00
HRESULT hr = SHParseDisplayName ( ConvertUTF8ToWString ( resolved ) . c_str ( ) , nullptr , & pidl , 0 , & flags ) ;
2021-10-09 15:58:49 -07:00
2019-05-21 23:22:56 +02:00
if ( pidl ) {
2021-10-09 15:58:49 -07:00
if ( SUCCEEDED ( hr ) )
SHOpenFolderAndSelectItems ( pidl , 0 , nullptr , 0 ) ;
CoTaskMemFree ( pidl ) ;
2019-05-21 23:22:56 +02:00
}
}
2013-08-26 19:00:16 +02:00
void LaunchBrowser ( const char * url ) {
ShellExecute ( NULL , L " open " , ConvertUTF8ToWString ( url ) . c_str ( ) , NULL , NULL , SW_SHOWNORMAL ) ;
2013-08-18 00:41:19 +02:00
}
2013-10-10 08:00:15 -07:00
void Vibrate ( int length_ms ) {
// Ignore on PC
}
2022-10-09 21:42:04 -07:00
static void AddDebugRestartArgs ( ) {
if ( LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > IsOpen ( ) )
restartArgs + = " -l " ;
}
2014-07-31 01:21:37 -04:00
// Adapted mostly as-is from http://www.gamedev.net/topic/495075-how-to-retrieve-info-about-videocard/?view=findpost&p=4229170
// so credit goes to that post's author, and in turn, the author of the site mentioned in that post (which seems to be down?).
2014-07-31 04:00:48 -04:00
std : : string GetVideoCardDriverVersion ( ) {
2014-07-31 01:21:37 -04:00
std : : string retvalue = " " ;
HRESULT hr ;
hr = CoInitializeEx ( NULL , COINIT_MULTITHREADED ) ;
2014-08-02 12:49:09 +02:00
if ( FAILED ( hr ) ) {
return retvalue ;
}
2014-07-31 01:21:37 -04:00
IWbemLocator * pIWbemLocator = NULL ;
2020-01-06 01:04:07 +08:00
hr = CoCreateInstance ( __uuidof ( WbemLocator ) , NULL , CLSCTX_INPROC_SERVER ,
2014-07-31 01:21:37 -04:00
__uuidof ( IWbemLocator ) , ( LPVOID * ) & pIWbemLocator ) ;
2014-08-02 12:49:09 +02:00
if ( FAILED ( hr ) ) {
CoUninitialize ( ) ;
return retvalue ;
}
2014-07-31 01:21:37 -04:00
BSTR bstrServer = SysAllocString ( L " \\ \\ . \\ root \\ cimv2 " ) ;
IWbemServices * pIWbemServices ;
hr = pIWbemLocator - > ConnectServer ( bstrServer , NULL , NULL , 0L , 0L , NULL , NULL , & pIWbemServices ) ;
2014-08-02 12:49:09 +02:00
if ( FAILED ( hr ) ) {
pIWbemLocator - > Release ( ) ;
2015-01-17 14:00:54 -08:00
SysFreeString ( bstrServer ) ;
2014-08-02 12:49:09 +02:00
CoUninitialize ( ) ;
return retvalue ;
}
2014-07-31 01:21:37 -04:00
2020-01-06 01:04:07 +08:00
hr = CoSetProxyBlanket ( pIWbemServices , RPC_C_AUTHN_WINNT , RPC_C_AUTHZ_NONE ,
2014-07-31 01:21:37 -04:00
NULL , RPC_C_AUTHN_LEVEL_CALL , RPC_C_IMP_LEVEL_IMPERSONATE , NULL , EOAC_DEFAULT ) ;
2020-01-06 01:04:07 +08:00
2014-07-31 01:21:37 -04:00
BSTR bstrWQL = SysAllocString ( L " WQL " ) ;
BSTR bstrPath = SysAllocString ( L " select * from Win32_VideoController " ) ;
IEnumWbemClassObject * pEnum ;
hr = pIWbemServices - > ExecQuery ( bstrWQL , bstrPath , WBEM_FLAG_FORWARD_ONLY , NULL , & pEnum ) ;
2022-12-10 21:09:50 -08:00
ULONG uReturned = 0 ;
VARIANT var { } ;
2014-08-02 12:49:09 +02:00
IWbemClassObject * pObj = NULL ;
if ( ! FAILED ( hr ) ) {
hr = pEnum - > Next ( WBEM_INFINITE , 1 , & pObj , & uReturned ) ;
}
2014-07-31 01:21:37 -04:00
2015-04-08 11:35:40 -07:00
if ( ! FAILED ( hr ) & & uReturned ) {
2014-07-31 01:21:37 -04:00
hr = pObj - > Get ( L " DriverVersion " , 0 , & var , NULL , NULL ) ;
if ( SUCCEEDED ( hr ) ) {
char str [ MAX_PATH ] ;
WideCharToMultiByte ( CP_ACP , 0 , var . bstrVal , - 1 , str , sizeof ( str ) , NULL , NULL ) ;
retvalue = str ;
}
}
pEnum - > Release ( ) ;
SysFreeString ( bstrPath ) ;
SysFreeString ( bstrWQL ) ;
pIWbemServices - > Release ( ) ;
2014-08-02 12:49:09 +02:00
pIWbemLocator - > Release ( ) ;
2014-07-31 01:21:37 -04:00
SysFreeString ( bstrServer ) ;
CoUninitialize ( ) ;
return retvalue ;
}
2013-09-04 11:29:38 +02:00
std : : string System_GetProperty ( SystemProperty prop ) {
2014-08-02 12:49:09 +02:00
static bool hasCheckedGPUDriverVersion = false ;
2013-09-04 11:29:38 +02:00
switch ( prop ) {
case SYSPROP_NAME :
2013-10-09 17:17:28 -04:00
return osName ;
2013-09-04 11:29:38 +02:00
case SYSPROP_LANGREGION :
2013-09-04 12:07:42 +02:00
return langRegion ;
2014-07-21 11:59:47 +02:00
case SYSPROP_CLIPBOARD_TEXT :
{
std : : string retval ;
if ( OpenClipboard ( MainWindow : : GetDisplayHWND ( ) ) ) {
HANDLE handle = GetClipboardData ( CF_UNICODETEXT ) ;
const wchar_t * wstr = ( const wchar_t * ) GlobalLock ( handle ) ;
2014-07-21 20:54:17 +08:00
if ( wstr )
retval = ConvertWStringToUTF8 ( wstr ) ;
else
2022-09-30 12:26:30 +03:00
retval . clear ( ) ;
2014-07-21 11:59:47 +02:00
GlobalUnlock ( handle ) ;
CloseClipboard ( ) ;
}
return retval ;
}
2014-07-31 01:21:37 -04:00
case SYSPROP_GPUDRIVER_VERSION :
2014-08-02 12:49:09 +02:00
if ( ! hasCheckedGPUDriverVersion ) {
hasCheckedGPUDriverVersion = true ;
gpuDriverVersion = GetVideoCardDriverVersion ( ) ;
}
2014-07-31 01:21:37 -04:00
return gpuDriverVersion ;
2013-09-04 11:29:38 +02:00
default :
return " " ;
}
2013-08-18 00:41:19 +02:00
}
2021-01-06 16:37:04 +01:00
std : : vector < std : : string > System_GetPropertyStringVec ( SystemProperty prop ) {
2021-01-09 14:45:49 -08:00
std : : vector < std : : string > result ;
2021-01-06 16:37:04 +01:00
switch ( prop ) {
2021-01-09 14:45:49 -08:00
case SYSPROP_TEMP_DIRS :
{
std : : wstring tempPath ( MAX_PATH , ' \0 ' ) ;
size_t sz = GetTempPath ( ( DWORD ) tempPath . size ( ) , & tempPath [ 0 ] ) ;
if ( sz > = tempPath . size ( ) ) {
tempPath . resize ( sz ) ;
sz = GetTempPath ( ( DWORD ) tempPath . size ( ) , & tempPath [ 0 ] ) ;
}
// Need to resize off the null terminator either way.
tempPath . resize ( sz ) ;
result . push_back ( ConvertWStringToUTF8 ( tempPath ) ) ;
if ( getenv ( " TMPDIR " ) & & strlen ( getenv ( " TMPDIR " ) ) ! = 0 )
result . push_back ( getenv ( " TMPDIR " ) ) ;
2021-01-10 20:33:17 +01:00
if ( getenv ( " TMP " ) & & strlen ( getenv ( " TMP " ) ) ! = 0 )
2021-01-09 14:45:49 -08:00
result . push_back ( getenv ( " TMP " ) ) ;
2021-01-10 20:33:17 +01:00
if ( getenv ( " TEMP " ) & & strlen ( getenv ( " TEMP " ) ) ! = 0 )
2021-01-09 14:45:49 -08:00
result . push_back ( getenv ( " TEMP " ) ) ;
return result ;
}
2021-01-06 16:37:04 +01:00
default :
2021-01-09 14:45:49 -08:00
return result ;
2021-01-06 16:37:04 +01:00
}
}
2015-01-11 21:00:56 +01:00
// Ugly!
extern WindowsAudioBackend * winAudioBackend ;
2017-03-17 13:22:00 +01:00
# ifdef _WIN32
# if PPSSPP_PLATFORM(UWP)
static int ScreenDPI ( ) {
return 96 ; // TODO UWP
}
# else
static int ScreenDPI ( ) {
HDC screenDC = GetDC ( nullptr ) ;
int dotsPerInch = GetDeviceCaps ( screenDC , LOGPIXELSY ) ;
ReleaseDC ( nullptr , screenDC ) ;
2017-04-30 08:54:34 +02:00
return dotsPerInch ? dotsPerInch : 96 ;
2017-03-17 13:22:00 +01:00
}
# endif
# endif
2023-01-04 16:33:00 +01:00
static int ScreenRefreshRateHz ( ) {
DEVMODE lpDevMode ;
memset ( & lpDevMode , 0 , sizeof ( DEVMODE ) ) ;
lpDevMode . dmSize = sizeof ( DEVMODE ) ;
lpDevMode . dmDriverExtra = 0 ;
if ( EnumDisplaySettings ( NULL , ENUM_CURRENT_SETTINGS , & lpDevMode ) = = 0 ) {
return 60 ; // default value
} else {
2023-01-05 13:07:36 +01:00
if ( lpDevMode . dmFields & DM_DISPLAYFREQUENCY ) {
2023-01-31 20:41:12 +01:00
return lpDevMode . dmDisplayFrequency > 60 ? lpDevMode . dmDisplayFrequency : 60 ;
2023-01-05 13:07:36 +01:00
} else {
return 60 ;
}
2023-01-04 16:33:00 +01:00
}
}
2014-07-20 12:11:50 +02:00
int System_GetPropertyInt ( SystemProperty prop ) {
2015-01-11 14:18:40 +01:00
switch ( prop ) {
case SYSPROP_AUDIO_SAMPLE_RATE :
2015-01-11 21:00:56 +01:00
return winAudioBackend ? winAudioBackend - > GetSampleRate ( ) : - 1 ;
2015-10-06 19:17:29 +02:00
case SYSPROP_DEVICE_TYPE :
return DEVICE_TYPE_DESKTOP ;
2017-07-30 08:33:02 -07:00
case SYSPROP_DISPLAY_COUNT :
return GetSystemMetrics ( SM_CMONITORS ) ;
2022-01-10 00:11:08 +00:00
case SYSPROP_KEYBOARD_LAYOUT :
{
HKL localeId = GetKeyboardLayout ( 0 ) ;
// TODO: Is this list complete enough?
switch ( ( int ) ( intptr_t ) localeId & 0xFFFF ) {
case 0x407 :
return KEYBOARD_LAYOUT_QWERTZ ;
case 0x040c :
case 0x080c :
case 0x1009 :
return KEYBOARD_LAYOUT_AZERTY ;
default :
return KEYBOARD_LAYOUT_QWERTY ;
}
}
2017-04-29 17:35:12 -07:00
default :
return - 1 ;
}
}
2020-01-06 01:04:07 +08:00
float System_GetPropertyFloat ( SystemProperty prop ) {
switch ( prop ) {
case SYSPROP_DISPLAY_REFRESH_RATE :
2023-01-04 16:33:00 +01:00
return ( float ) ScreenRefreshRateHz ( ) ;
2020-01-06 01:04:07 +08:00
case SYSPROP_DISPLAY_DPI :
return ( float ) ScreenDPI ( ) ;
2020-04-05 17:06:36 -07:00
case SYSPROP_DISPLAY_SAFE_INSET_LEFT :
case SYSPROP_DISPLAY_SAFE_INSET_RIGHT :
case SYSPROP_DISPLAY_SAFE_INSET_TOP :
case SYSPROP_DISPLAY_SAFE_INSET_BOTTOM :
return 0.0f ;
2020-01-06 01:04:07 +08:00
default :
return - 1 ;
}
}
2017-04-29 17:35:12 -07:00
bool System_GetPropertyBool ( SystemProperty prop ) {
switch ( prop ) {
2017-02-27 11:32:40 +01:00
case SYSPROP_HAS_FILE_BROWSER :
2020-12-20 01:28:43 +01:00
case SYSPROP_HAS_FOLDER_BROWSER :
2023-02-02 14:54:50 +01:00
case SYSPROP_HAS_OPEN_DIRECTORY :
2017-04-29 17:35:12 -07:00
return true ;
2017-04-02 10:50:09 -07:00
case SYSPROP_HAS_IMAGE_BROWSER :
2017-04-29 17:35:12 -07:00
return true ;
2017-03-07 10:33:53 +01:00
case SYSPROP_HAS_BACK_BUTTON :
2017-04-29 17:35:12 -07:00
return true ;
2017-04-05 16:21:08 +02:00
case SYSPROP_APP_GOLD :
# ifdef GOLD
2017-04-29 17:35:12 -07:00
return true ;
2017-04-05 16:21:08 +02:00
# else
2017-04-29 17:35:12 -07:00
return false ;
2017-04-05 16:21:08 +02:00
# endif
2021-02-21 22:02:11 +01:00
case SYSPROP_CAN_JIT :
return true ;
2021-04-25 22:54:28 -07:00
case SYSPROP_HAS_KEYBOARD :
return true ;
2022-07-10 22:34:44 +02:00
case SYSPROP_SUPPORTS_OPEN_FILE_IN_EDITOR :
return true ; // FileUtil.cpp: OpenFileInEditor
2015-01-11 14:18:40 +01:00
default :
2017-04-29 17:35:12 -07:00
return false ;
2015-01-11 14:18:40 +01:00
}
2014-07-20 12:11:50 +02:00
}
2014-04-26 01:00:45 -04:00
void System_SendMessage ( const char * command , const char * parameter ) {
if ( ! strcmp ( command , " finish " ) ) {
2017-04-15 16:33:30 -07:00
if ( ! NativeIsRestarting ( ) ) {
PostMessage ( MainWindow : : GetHWND ( ) , WM_CLOSE , 0 , 0 ) ;
}
} else if ( ! strcmp ( command , " graphics_restart " ) ) {
2020-05-09 13:52:04 -07:00
restartArgs = parameter = = nullptr ? " " : parameter ;
2022-10-09 21:42:04 -07:00
if ( ! restartArgs . empty ( ) )
AddDebugRestartArgs ( ) ;
2017-05-21 17:24:40 +02:00
if ( IsDebuggerPresent ( ) ) {
PostMessage ( MainWindow : : GetHWND ( ) , MainWindow : : WM_USER_RESTART_EMUTHREAD , 0 , 0 ) ;
} else {
g_Config . bRestartRequired = true ;
PostMessage ( MainWindow : : GetHWND ( ) , WM_CLOSE , 0 , 0 ) ;
}
2020-03-28 06:19:11 -07:00
} else if ( ! strcmp ( command , " graphics_failedBackend " ) ) {
auto err = GetI18NCategory ( " Error " ) ;
2020-05-08 23:20:37 -07:00
const char * backendSwitchError = err - > T ( " GenericBackendSwitchCrash " , " PPSSPP crashed while starting. This usually means a graphics driver problem. Try upgrading your graphics drivers. \n \n Graphics backend has been switched: " ) ;
2020-03-28 06:19:11 -07:00
std : : wstring full_error = ConvertUTF8ToWString ( StringFromFormat ( " %s %s " , backendSwitchError , parameter ) ) ;
std : : wstring title = ConvertUTF8ToWString ( err - > T ( " GenericGraphicsError " , " Graphics Error " ) ) ;
MessageBox ( MainWindow : : GetHWND ( ) , full_error . c_str ( ) , title . c_str ( ) , MB_OK ) ;
2014-07-21 17:36:25 +02:00
} else if ( ! strcmp ( command , " setclipboardtext " ) ) {
2022-12-10 21:09:50 -08:00
std : : wstring data = ConvertUTF8ToWString ( parameter ) ;
W32Util : : CopyTextToClipboard ( MainWindow : : GetDisplayHWND ( ) , data ) ;
2017-04-02 10:50:09 -07:00
} else if ( ! strcmp ( command , " browse_file " ) ) {
MainWindow : : BrowseAndBoot ( " " ) ;
2019-02-17 08:03:10 -08:00
} else if ( ! strcmp ( command , " browse_folder " ) ) {
2020-01-26 10:43:18 -08:00
auto mm = GetI18NCategory ( " MainMenu " ) ;
2019-02-17 08:03:10 -08:00
std : : string folder = W32Util : : BrowseForFolder ( MainWindow : : GetHWND ( ) , mm - > T ( " Choose folder " ) ) ;
if ( folder . size ( ) )
NativeMessageReceived ( " browse_folderSelect " , folder . c_str ( ) ) ;
2017-04-02 10:50:09 -07:00
} else if ( ! strcmp ( command , " bgImage_browse " ) ) {
MainWindow : : BrowseBackground ( ) ;
2017-07-30 07:51:53 -07:00
} else if ( ! strcmp ( command , " toggle_fullscreen " ) ) {
2021-01-09 14:17:41 -08:00
bool flag = ! MainWindow : : IsFullscreen ( ) ;
2017-07-30 07:51:53 -07:00
if ( strcmp ( parameter , " 0 " ) = = 0 ) {
flag = false ;
} else if ( strcmp ( parameter , " 1 " ) = = 0 ) {
flag = true ;
}
MainWindow : : SendToggleFullscreen ( flag ) ;
2014-04-26 01:00:45 -04:00
}
}
2013-12-04 17:41:59 +01:00
2015-12-17 22:41:50 +01:00
void System_AskForPermission ( SystemPermission permission ) { }
PermissionStatus System_GetPermissionStatus ( SystemPermission permission ) { return PERMISSION_STATUS_GRANTED ; }
2015-01-17 12:32:58 -08:00
void EnableCrashingOnCrashes ( ) {
typedef BOOL ( WINAPI * tGetPolicy ) ( LPDWORD lpFlags ) ;
typedef BOOL ( WINAPI * tSetPolicy ) ( DWORD dwFlags ) ;
const DWORD EXCEPTION_SWALLOWING = 0x1 ;
HMODULE kernel32 = LoadLibrary ( L " kernel32.dll " ) ;
2022-12-10 21:09:50 -08:00
if ( ! kernel32 )
return ;
2015-01-17 12:32:58 -08:00
tGetPolicy pGetPolicy = ( tGetPolicy ) GetProcAddress ( kernel32 ,
" GetProcessUserModeExceptionPolicy " ) ;
tSetPolicy pSetPolicy = ( tSetPolicy ) GetProcAddress ( kernel32 ,
" SetProcessUserModeExceptionPolicy " ) ;
if ( pGetPolicy & & pSetPolicy ) {
DWORD dwFlags ;
if ( pGetPolicy ( & dwFlags ) ) {
// Turn off the filter.
pSetPolicy ( dwFlags & ~ EXCEPTION_SWALLOWING ) ;
}
}
FreeLibrary ( kernel32 ) ;
2013-11-13 02:50:35 +10:00
}
2020-03-08 18:59:17 -07:00
void System_InputBoxGetString ( const std : : string & title , const std : : string & defaultValue , std : : function < void ( bool , const std : : string & ) > cb ) {
2021-02-18 07:27:28 -08:00
if ( inputBoxRunning ) {
inputBoxThread . join ( ) ;
2013-12-08 20:16:18 +10:00
}
2021-02-18 07:27:28 -08:00
inputBoxRunning = true ;
inputBoxThread = std : : thread ( [ = ] {
std : : string out ;
if ( InputBox_GetString ( MainWindow : : GetHInstance ( ) , MainWindow : : GetHWND ( ) , ConvertUTF8ToWString ( title ) . c_str ( ) , defaultValue , out ) ) {
NativeInputBoxReceived ( cb , true , out ) ;
} else {
NativeInputBoxReceived ( cb , false , " " ) ;
}
} ) ;
2013-12-08 20:16:18 +10:00
}
2022-07-10 22:34:44 +02:00
void System_Toast ( const char * text ) {
// Not-very-good implementation. Will normally not be used on Windows anyway.
std : : wstring str = ConvertUTF8ToWString ( text ) ;
MessageBox ( 0 , str . c_str ( ) , L " Toast! " , MB_ICONINFORMATION ) ;
}
2015-12-25 19:14:05 -08:00
static std : : string GetDefaultLangRegion ( ) {
wchar_t lcLangName [ 256 ] = { } ;
// LOCALE_SNAME is only available in WinVista+
if ( 0 ! = GetLocaleInfo ( LOCALE_NAME_USER_DEFAULT , LOCALE_SNAME , lcLangName , ARRAY_SIZE ( lcLangName ) ) ) {
std : : string result = ConvertWStringToUTF8 ( lcLangName ) ;
std : : replace ( result . begin ( ) , result . end ( ) , ' - ' , ' _ ' ) ;
return result ;
} else {
// This should work on XP, but we may get numbers for some countries.
if ( 0 ! = GetLocaleInfo ( LOCALE_USER_DEFAULT , LOCALE_SISO639LANGNAME , lcLangName , ARRAY_SIZE ( lcLangName ) ) ) {
wchar_t lcRegion [ 256 ] = { } ;
if ( 0 ! = GetLocaleInfo ( LOCALE_USER_DEFAULT , LOCALE_SISO3166CTRYNAME , lcRegion , ARRAY_SIZE ( lcRegion ) ) ) {
return ConvertWStringToUTF8 ( lcLangName ) + " _ " + ConvertWStringToUTF8 ( lcRegion ) ;
}
}
// Unfortunate default. We tried.
return " en_US " ;
}
}
2014-02-17 03:30:38 -05:00
2019-02-16 10:14:54 -08:00
static const int EXIT_CODE_VULKAN_WORKS = 42 ;
2021-02-15 09:28:07 -08:00
# ifndef _DEBUG
2019-02-16 10:14:54 -08:00
static bool DetectVulkanInExternalProcess ( ) {
2020-01-04 09:02:10 -08:00
std : : wstring workingDirectory ;
std : : wstring moduleFilename ;
W32Util : : GetSelfExecuteParams ( workingDirectory , moduleFilename ) ;
2019-02-16 10:14:54 -08:00
const wchar_t * cmdline = L " --vulkan-available-check " ;
SHELLEXECUTEINFO info { sizeof ( SHELLEXECUTEINFO ) } ;
info . fMask = SEE_MASK_NOCLOSEPROCESS ;
2020-01-04 09:02:10 -08:00
info . lpFile = moduleFilename . c_str ( ) ;
2019-02-16 10:14:54 -08:00
info . lpParameters = cmdline ;
2020-01-04 09:02:10 -08:00
info . lpDirectory = workingDirectory . c_str ( ) ;
2019-02-16 10:14:54 -08:00
info . nShow = SW_HIDE ;
if ( ShellExecuteEx ( & info ) ! = TRUE ) {
return false ;
}
if ( info . hProcess = = nullptr ) {
return false ;
}
DWORD result = WaitForSingleObject ( info . hProcess , 10000 ) ;
DWORD exitCode = 0 ;
if ( result = = WAIT_FAILED | | GetExitCodeProcess ( info . hProcess , & exitCode ) = = 0 ) {
CloseHandle ( info . hProcess ) ;
return false ;
}
CloseHandle ( info . hProcess ) ;
return exitCode = = EXIT_CODE_VULKAN_WORKS ;
}
2021-02-15 09:28:07 -08:00
# endif
2019-02-16 10:14:54 -08:00
2014-08-31 01:17:25 -04:00
std : : vector < std : : wstring > GetWideCmdLine ( ) {
wchar_t * * wargv ;
int wargc = - 1 ;
2020-05-09 13:52:04 -07:00
// This is used for the WM_USER_RESTART_EMUTHREAD path.
if ( ! restartArgs . empty ( ) ) {
std : : wstring wargs = ConvertUTF8ToWString ( " PPSSPP " + restartArgs ) ;
wargv = CommandLineToArgvW ( wargs . c_str ( ) , & wargc ) ;
restartArgs . clear ( ) ;
} else {
wargv = CommandLineToArgvW ( GetCommandLineW ( ) , & wargc ) ;
}
2014-08-31 01:17:25 -04:00
std : : vector < std : : wstring > wideArgs ( wargv , wargv + wargc ) ;
2018-01-17 19:25:01 +09:00
LocalFree ( wargv ) ;
2014-08-31 01:17:25 -04:00
return wideArgs ;
}
2019-02-16 10:14:54 -08:00
static void WinMainInit ( ) {
2015-01-15 22:32:25 +01:00
CoInitializeEx ( NULL , COINIT_MULTITHREADED ) ;
2017-03-12 17:24:46 +01:00
net : : Init ( ) ; // This needs to happen before we load the config. So on Windows we also run it in Main. It's fine to call multiple times.
2017-03-06 10:51:28 +01:00
// Windows, API init stuff
INITCOMMONCONTROLSEX comm ;
comm . dwSize = sizeof ( comm ) ;
comm . dwICC = ICC_BAR_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES ;
InitCommonControlsEx ( & comm ) ;
EnableCrashingOnCrashes ( ) ;
2015-10-04 12:24:59 +02:00
# ifdef _DEBUG
2016-02-10 15:22:28 +01:00
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ) ;
2015-10-04 12:24:59 +02:00
# endif
2015-05-12 19:45:14 +02:00
PROFILE_INIT ( ) ;
2014-02-17 03:30:38 -05:00
2021-03-02 21:49:21 -08:00
# if PPSSPP_ARCH(AMD64) && defined(_MSC_VER) && _MSC_VER < 1900
2014-02-13 15:57:36 +01:00
// FMA3 support in the 2013 CRT is broken on Vista and Windows 7 RTM (fixed in SP1). Just disable it.
_set_FMA3_enable ( 0 ) ;
2014-02-13 16:02:10 +01:00
# endif
2020-05-04 17:33:39 +02:00
InitDarkMode ( ) ;
2019-02-16 10:14:54 -08:00
}
static void WinMainCleanup ( ) {
2021-02-18 07:27:28 -08:00
if ( inputBoxRunning ) {
inputBoxThread . join ( ) ;
inputBoxRunning = false ;
}
2019-02-16 10:14:54 -08:00
net : : Shutdown ( ) ;
CoUninitialize ( ) ;
2020-05-09 13:52:04 -07:00
if ( g_Config . bRestartRequired ) {
W32Util : : ExitAndRestart ( ! restartArgs . empty ( ) , restartArgs ) ;
}
2019-02-16 10:14:54 -08:00
}
int WINAPI WinMain ( HINSTANCE _hInstance , HINSTANCE hPrevInstance , LPSTR szCmdLine , int iCmdShow ) {
2020-12-01 00:46:26 +01:00
SetCurrentThreadName ( " Main " ) ;
2019-02-16 10:14:54 -08:00
WinMainInit ( ) ;
2014-02-13 15:57:36 +01:00
2013-10-13 12:27:05 -07:00
# ifndef _DEBUG
2013-10-15 22:27:03 -07:00
bool showLog = false ;
2013-10-13 12:27:05 -07:00
# else
2015-12-25 19:14:05 -08:00
bool showLog = true ;
2013-10-13 12:27:05 -07:00
# endif
2021-05-15 09:59:25 -07:00
const Path & exePath = File : : GetExeDirectory ( ) ;
2023-03-06 15:30:39 +01:00
g_VFS . Register ( " " , new DirectoryReader ( exePath / " assets " ) ) ;
g_VFS . Register ( " " , new DirectoryReader ( exePath ) ) ;
2013-09-15 11:02:13 +02:00
2015-12-25 19:14:05 -08:00
langRegion = GetDefaultLangRegion ( ) ;
2013-10-09 17:17:28 -04:00
osName = GetWindowsVersion ( ) + " " + GetWindowsSystemArchitecture ( ) ;
2018-01-18 00:36:27 +09:00
std : : string configFilename = " " ;
2014-08-31 01:17:25 -04:00
const std : : wstring configOption = L " --config= " ;
2013-09-15 12:50:42 -04:00
2018-01-18 00:36:27 +09:00
std : : string controlsConfigFilename = " " ;
2014-08-31 01:17:25 -04:00
const std : : wstring controlsOption = L " --controlconfig= " ;
2013-09-15 12:50:42 -04:00
2014-08-31 01:17:25 -04:00
std : : vector < std : : wstring > wideArgs = GetWideCmdLine ( ) ;
2014-09-12 16:58:05 -04:00
for ( size_t i = 1 ; i < wideArgs . size ( ) ; + + i ) {
2014-08-31 01:17:25 -04:00
if ( wideArgs [ i ] [ 0 ] = = L ' \0 ' )
2013-09-15 12:50:42 -04:00
continue ;
2014-08-31 01:17:25 -04:00
if ( wideArgs [ i ] [ 0 ] = = L ' - ' ) {
if ( wideArgs [ i ] . find ( configOption ) ! = std : : wstring : : npos & & wideArgs [ i ] . size ( ) > configOption . size ( ) ) {
const std : : wstring tempWide = wideArgs [ i ] . substr ( configOption . size ( ) ) ;
2018-01-18 00:36:27 +09:00
configFilename = ConvertWStringToUTF8 ( tempWide ) ;
2013-09-15 12:50:42 -04:00
}
2014-08-31 01:17:25 -04:00
if ( wideArgs [ i ] . find ( controlsOption ) ! = std : : wstring : : npos & & wideArgs [ i ] . size ( ) > controlsOption . size ( ) ) {
2014-11-02 20:38:00 +01:00
const std : : wstring tempWide = wideArgs [ i ] . substr ( controlsOption . size ( ) ) ;
2018-01-18 00:36:27 +09:00
controlsConfigFilename = ConvertWStringToUTF8 ( tempWide ) ;
2013-09-15 12:50:42 -04:00
}
}
}
2020-08-15 18:40:50 +02:00
LogManager : : Init ( & g_Config . bEnableLogging ) ;
2017-03-06 11:44:35 +01:00
2020-01-06 01:04:07 +08:00
// On Win32 it makes more sense to initialize the system directories here
2013-10-15 02:28:14 -04:00
// because the next place it was called was in the EmuThread, and it's too late by then.
2021-05-15 09:32:41 -07:00
g_Config . internalDataDirectory = Path ( W32Util : : UserDocumentsPath ( ) ) ;
2013-10-15 02:03:39 -04:00
InitSysDirectories ( ) ;
2013-09-15 12:50:42 -04:00
2020-08-18 00:47:22 -07:00
// Check for the Vulkan workaround before any serious init.
for ( size_t i = 1 ; i < wideArgs . size ( ) ; + + i ) {
if ( wideArgs [ i ] [ 0 ] = = L ' - ' ) {
// This should only be called by DetectVulkanInExternalProcess().
if ( wideArgs [ i ] = = L " --vulkan-available-check " ) {
// Just call it, this way it will crash here if it doesn't work.
// (this is an external process.)
bool result = VulkanMayBeAvailable ( ) ;
LogManager : : Shutdown ( ) ;
WinMainCleanup ( ) ;
return result ? EXIT_CODE_VULKAN_WORKS : EXIT_FAILURE ;
}
}
}
2013-09-12 16:56:18 -04:00
// Load config up here, because those changes below would be overwritten
// if it's not loaded here first.
2021-05-30 12:45:12 +02:00
g_Config . SetSearchPath ( GetSysDirectory ( DIRECTORY_SYSTEM ) ) ;
2018-01-18 00:36:27 +09:00
g_Config . Load ( configFilename . c_str ( ) , controlsConfigFilename . c_str ( ) ) ;
2013-09-12 16:56:18 -04:00
2014-03-31 22:44:05 -04:00
bool debugLogLevel = false ;
2014-09-13 01:33:45 -04:00
const std : : wstring gpuBackend = L " --graphics= " ;
2014-09-12 16:16:13 -04:00
2013-03-31 18:22:27 -07:00
// The rest is handled in NativeInit().
2014-09-12 16:58:05 -04:00
for ( size_t i = 1 ; i < wideArgs . size ( ) ; + + i ) {
2014-08-31 01:17:25 -04:00
if ( wideArgs [ i ] [ 0 ] = = L ' \0 ' )
2012-12-22 09:21:23 -08:00
continue ;
2014-08-31 01:17:25 -04:00
if ( wideArgs [ i ] [ 0 ] = = L ' - ' ) {
switch ( wideArgs [ i ] [ 1 ] ) {
case L ' l ' :
2013-10-15 22:27:03 -07:00
showLog = true ;
2013-10-13 14:25:59 -04:00
g_Config . bEnableLogging = true ;
2012-12-22 09:21:23 -08:00
break ;
2014-08-31 01:17:25 -04:00
case L ' s ' :
2013-01-04 10:26:14 +01:00
g_Config . bAutoRun = false ;
g_Config . bSaveSettings = false ;
2012-12-22 09:21:23 -08:00
break ;
2014-08-31 01:17:25 -04:00
case L ' d ' :
2014-03-31 22:44:05 -04:00
debugLogLevel = true ;
break ;
2012-12-22 09:21:23 -08:00
}
2013-09-12 16:56:18 -04:00
2014-09-12 16:58:05 -04:00
if ( wideArgs [ i ] . find ( gpuBackend ) ! = std : : wstring : : npos & & wideArgs [ i ] . size ( ) > gpuBackend . size ( ) ) {
2014-09-12 16:16:13 -04:00
const std : : wstring restOfOption = wideArgs [ i ] . substr ( gpuBackend . size ( ) ) ;
2014-09-13 01:33:45 -04:00
// Force software rendering off, as picking directx9 or gles implies HW acceleration.
// Once software rendering supports Direct3D9/11, we can add more options for software,
// such as "software-gles", "software-d3d9", and "software-d3d11", or something similar.
// For now, software rendering force-activates OpenGL.
if ( restOfOption = = L " directx9 " ) {
2017-12-26 15:55:24 -08:00
g_Config . iGPUBackend = ( int ) GPUBackend : : DIRECT3D9 ;
2014-09-13 01:33:45 -04:00
g_Config . bSoftwareRendering = false ;
2017-02-16 11:30:58 +01:00
} else if ( restOfOption = = L " directx11 " ) {
2017-12-26 15:55:24 -08:00
g_Config . iGPUBackend = ( int ) GPUBackend : : DIRECT3D11 ;
2017-02-16 11:30:58 +01:00
g_Config . bSoftwareRendering = false ;
2016-02-13 12:22:06 -08:00
} else if ( restOfOption = = L " gles " ) {
2017-12-26 15:55:24 -08:00
g_Config . iGPUBackend = ( int ) GPUBackend : : OPENGL ;
2014-09-13 01:33:45 -04:00
g_Config . bSoftwareRendering = false ;
2017-02-16 11:30:58 +01:00
} else if ( restOfOption = = L " vulkan " ) {
2017-12-26 15:55:24 -08:00
g_Config . iGPUBackend = ( int ) GPUBackend : : VULKAN ;
2017-02-16 11:30:58 +01:00
g_Config . bSoftwareRendering = false ;
2016-02-13 12:22:06 -08:00
} else if ( restOfOption = = L " software " ) {
2017-12-26 15:55:24 -08:00
g_Config . iGPUBackend = ( int ) GPUBackend : : OPENGL ;
2014-09-13 01:33:45 -04:00
g_Config . bSoftwareRendering = true ;
}
2014-09-12 16:16:13 -04:00
}
2012-12-22 09:21:23 -08:00
}
2012-11-01 16:19:01 +01:00
}
2013-10-13 14:25:59 -04:00
# ifdef _DEBUG
g_Config . bEnableLogging = true ;
# endif
2012-11-01 16:19:01 +01:00
2019-02-16 10:14:54 -08:00
# ifndef _DEBUG
// See #11719 - too many Vulkan drivers crash on basic init.
2019-06-30 23:45:14 -07:00
if ( g_Config . IsBackendEnabled ( GPUBackend : : VULKAN , false ) ) {
2019-06-22 11:48:36 -07:00
VulkanSetAvailable ( DetectVulkanInExternalProcess ( ) ) ;
}
2019-02-16 10:14:54 -08:00
# endif
2015-12-25 19:18:32 -08:00
if ( iCmdShow = = SW_MAXIMIZE ) {
// Consider this to mean --fullscreen.
2022-05-28 15:47:12 -07:00
g_Config . iForceFullScreen = 1 ;
2015-12-25 19:18:32 -08:00
}
2013-10-13 12:27:05 -07:00
// Consider at least the following cases before changing this code:
// - By default in Release, the console should be hidden by default even if logging is enabled.
// - By default in Debug, the console should be shown by default.
// - The -l switch is expected to show the log console, REGARDLESS of config settings.
// - It should be possible to log to a file without showing the console.
2013-10-15 22:27:03 -07:00
LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > Init ( showLog , 150 , 120 , " PPSSPP Debug Console " ) ;
2020-01-06 01:04:07 +08:00
2020-08-15 19:01:16 +02:00
if ( debugLogLevel ) {
2014-03-31 22:44:05 -04:00
LogManager : : GetInstance ( ) - > SetAllLogLevels ( LogTypes : : LDEBUG ) ;
2020-08-15 19:01:16 +02:00
}
2013-06-08 08:32:07 +08:00
2022-01-30 08:23:14 -08:00
// This still seems to improve performance noticeably.
timeBeginPeriod ( 1 ) ;
2017-03-06 10:51:28 +01:00
2021-10-07 19:53:40 -07:00
ContextMenuInit ( _hInstance ) ;
2012-11-01 16:19:01 +01:00
MainWindow : : Init ( _hInstance ) ;
2014-07-17 00:06:52 -04:00
MainWindow : : Show ( _hInstance ) ;
2012-11-01 16:19:01 +01:00
HWND hwndMain = MainWindow : : GetHWND ( ) ;
2020-01-06 01:04:07 +08:00
2012-11-01 16:19:01 +01:00
//initialize custom controls
CtrlDisAsmView : : init ( ) ;
CtrlMemView : : init ( ) ;
CtrlRegisterList : : init ( ) ;
2019-05-10 23:25:57 +02:00
# if PPSSPP_API(ANY_GL)
2013-09-27 22:41:44 -07:00
CGEDebugger : : Init ( ) ;
2019-05-04 06:06:50 +08:00
# endif
2012-11-01 16:19:01 +01:00
2021-11-13 22:10:37 +01:00
if ( g_Config . bShowDebuggerOnLoad ) {
MainWindow : : CreateDisasmWindow ( ) ;
disasmWindow - > Show ( g_Config . bShowDebuggerOnLoad , false ) ;
}
2013-08-26 14:19:46 +02:00
2015-12-25 19:18:32 -08:00
const bool minimized = iCmdShow = = SW_MINIMIZE | | iCmdShow = = SW_SHOWMINIMIZED | | iCmdShow = = SW_SHOWMINNOACTIVE ;
if ( minimized ) {
MainWindow : : Minimize ( ) ;
}
2017-12-15 12:40:38 +01:00
// Emu thread (and render thread, if any) is always running!
2018-01-16 14:16:56 +01:00
// Only OpenGL uses an externally managed render thread (due to GL's single-threaded context design). Vulkan
// manages its own render thread.
2018-02-07 15:52:19 +01:00
MainThread_Start ( g_Config . iGPUBackend = = ( int ) GPUBackend : : OPENGL ) ;
2014-03-23 22:18:54 -07:00
InputDevice : : BeginPolling ( ) ;
2013-03-29 18:50:08 +01:00
2013-06-08 08:32:07 +08:00
HACCEL hAccelTable = LoadAccelerators ( _hInstance , ( LPCTSTR ) IDR_ACCELS ) ;
2013-08-14 23:30:50 +02:00
HACCEL hDebugAccelTable = LoadAccelerators ( _hInstance , ( LPCTSTR ) IDR_DEBUGACCELS ) ;
2012-12-22 09:21:23 -08:00
2012-11-01 16:19:01 +01:00
//so.. we're at the message pump of the GUI thread
2013-06-08 08:32:07 +08:00
for ( MSG msg ; GetMessage ( & msg , NULL , 0 , 0 ) ; ) // for no quit
2012-11-01 16:19:01 +01:00
{
2013-05-13 16:08:10 +08:00
if ( msg . message = = WM_KEYDOWN )
{
//hack to enable/disable menu command accelerate keys
MainWindow : : UpdateCommands ( ) ;
2020-01-06 01:04:07 +08:00
2013-05-13 16:08:10 +08:00
//hack to make it possible to get to main window from floating windows with Esc
if ( msg . hwnd ! = hwndMain & & msg . wParam = = VK_ESCAPE )
BringWindowToTop ( hwndMain ) ;
}
2012-11-01 16:19:01 +01:00
//Translate accelerators and dialog messages...
2013-08-14 23:46:59 +02:00
HWND wnd ;
HACCEL accel ;
2013-09-28 14:34:08 +02:00
switch ( g_activeWindow )
{
case WINDOW_MAINWINDOW :
2013-08-14 23:46:59 +02:00
wnd = hwndMain ;
2021-02-27 14:40:02 -08:00
accel = g_Config . bSystemControls ? hAccelTable : NULL ;
2013-09-28 14:34:08 +02:00
break ;
case WINDOW_CPUDEBUGGER :
2021-02-27 14:40:02 -08:00
wnd = disasmWindow ? disasmWindow - > GetDlgHandle ( ) : NULL ;
accel = g_Config . bSystemControls ? hDebugAccelTable : NULL ;
2013-09-28 14:34:08 +02:00
break ;
case WINDOW_GEDEBUGGER :
default :
2021-02-27 14:40:02 -08:00
wnd = NULL ;
accel = NULL ;
2013-09-28 14:34:08 +02:00
break ;
2013-08-14 23:46:59 +02:00
}
2022-12-10 21:09:50 -08:00
if ( ! wnd | | ! accel | | ! TranslateAccelerator ( wnd , accel , & msg ) ) {
2018-02-10 09:06:43 +01:00
if ( ! DialogManager : : IsDialogMessage ( & msg ) ) {
2012-11-01 16:19:01 +01:00
//and finally translate and dispatch
TranslateMessage ( & msg ) ;
DispatchMessage ( & msg ) ;
}
}
}
2023-03-06 14:23:56 +01:00
g_VFS . Clear ( ) ;
2013-02-08 10:35:05 -08:00
2014-02-14 21:17:36 -08:00
MainWindow : : DestroyDebugWindows ( ) ;
2012-11-01 16:19:01 +01:00
DialogManager : : DestroyAll ( ) ;
2012-12-03 16:44:37 +08:00
timeEndPeriod ( 1 ) ;
2014-09-14 06:59:27 -04:00
2013-06-26 00:31:52 -07:00
LogManager : : Shutdown ( ) ;
2019-02-16 10:14:54 -08:00
WinMainCleanup ( ) ;
2015-10-04 12:24:59 +02:00
2012-11-01 16:19:01 +01:00
return 0 ;
}