2014-01-04 12:33:02 +01:00
// Copyright (c) 2012- PPSSPP Project.
2013-07-29 05:23:27 -04:00
// 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/.
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-07-29 05:23:27 -04:00
// It's improving slowly, though. :)
2012-11-01 16:19:01 +01:00
2013-07-28 21:01:49 -07:00
# include "Common/CommonWindows.h"
2014-06-04 19:15:41 +03:00
# include "Common/KeyMap.h"
2013-03-29 18:50:08 +01:00
2013-07-06 21:49:28 +02:00
# include <map>
2013-09-01 14:06:24 -07:00
# include <string>
2013-07-06 21:49:28 +02:00
2013-03-29 18:50:08 +01:00
# include "base/NativeApp.h"
2013-03-11 22:55:29 +01:00
# include "Globals.h"
2012-11-01 16:19:01 +01:00
# include "shellapi.h"
# include "commctrl.h"
2013-08-26 19:00:16 +02:00
# include "i18n/i18n.h"
2013-03-29 18:50:08 +01:00
# include "input/input_state.h"
2013-07-08 12:35:08 +02:00
# include "input/keycodes.h"
2014-06-29 12:53:03 +02:00
# include "thread/threadutil.h"
2013-08-26 19:00:16 +02:00
# include "util/text/utf8.h"
2013-03-11 22:55:29 +01:00
# include "Core/Debugger/SymbolMap.h"
2014-01-01 16:45:37 -08:00
# include "Windows/InputBox.h"
2013-03-11 22:55:29 +01:00
# include "Windows/OpenGLBase.h"
# include "Windows/Debugger/Debugger_Disasm.h"
# include "Windows/Debugger/Debugger_MemoryDlg.h"
2013-09-22 11:03:29 -07:00
# include "Windows/GEDebugger/GEDebugger.h"
2012-11-01 16:19:01 +01:00
# include "main.h"
2013-03-11 22:55:29 +01:00
# include "Core/Core.h"
# include "Core/MemMap.h"
# include "Core/SaveState.h"
# include "Core/System.h"
# include "Core/Config.h"
2014-12-13 00:09:37 +01:00
# include "Core/MIPS/JitCommon/NativeJit.h"
2013-11-30 18:21:47 -08:00
# include "Core/MIPS/JitCommon/JitBlockCache.h"
2014-01-01 16:45:37 -08:00
# include "Core/FileSystems/MetaFileSystem.h"
2013-03-11 22:55:29 +01:00
# include "Windows/EmuThread.h"
2012-11-01 16:19:01 +01:00
# include "resource.h"
2013-03-11 22:55:29 +01:00
# include "Windows/WndMainWindow.h"
2013-07-06 19:08:59 +02:00
# include "Windows/WindowsHost.h"
2013-03-11 22:55:29 +01:00
# include "Common/LogManager.h"
# include "Common/ConsoleListener.h"
# include "Windows/W32Util/DialogManager.h"
# include "Windows/W32Util/ShellUtil.h"
# include "Windows/W32Util/Misc.h"
2014-01-19 11:59:11 -08:00
# include "Windows/RawInput.h"
2014-01-19 22:54:49 +01:00
# include "Windows/TouchInputHandler.h"
2013-03-11 22:55:29 +01:00
# include "GPU/GPUInterface.h"
2014-01-19 21:14:21 -08:00
# include "gfx_es2/gpu_features.h"
2015-01-22 19:53:32 +01:00
# include "GPU/GLES/TextureScaler.h"
2013-07-29 04:46:40 -04:00
# include "GPU/GLES/TextureCache.h"
# include "GPU/GLES/Framebuffer.h"
2013-05-22 18:00:06 +02:00
# include "UI/OnScreenDisplay.h"
2013-10-12 00:14:58 -04:00
# include "GPU/Common/PostShader.h"
2012-11-01 16:19:01 +01:00
2013-11-27 21:57:17 +08:00
# include "Core/HLE/sceUmd.h"
2012-11-01 16:19:01 +01:00
# ifdef THEMES
# include "XPTheme.h"
# endif
2014-02-24 13:28:20 +01:00
# define MOUSEEVENTF_FROMTOUCH_NOPEN 0xFF515780 //http://msdn.microsoft.com/en-us/library/windows/desktop/ms703320(v=vs.85).aspx
# define MOUSEEVENTF_MASK_PLUS_PENTOUCH 0xFFFFFF80
2014-01-23 18:05:42 +01:00
2013-12-29 15:55:09 -08:00
static const int numCPUs = 1 ;
2013-11-30 18:21:47 -08:00
int verysleepy__useSendMessage = 1 ;
const UINT WM_VERYSLEEPY_MSG = WM_APP + 0x3117 ;
// Respond TRUE to a message with this param value to indicate support.
const WPARAM VERYSLEEPY_WPARAM_SUPPORTED = 0 ;
// Respond TRUE to a message wit this param value after filling in the addr name.
const WPARAM VERYSLEEPY_WPARAM_GETADDRINFO = 1 ;
2014-06-29 22:13:53 +02:00
struct VerySleepy_AddrInfo
{
2013-11-30 18:21:47 -08:00
// Always zero for now.
int flags ;
// This is the pointer (always passed as 64 bits.)
unsigned long long addr ;
// Write the name here.
wchar_t name [ 256 ] ;
} ;
2013-07-06 21:49:28 +02:00
extern std : : map < int , int > windowsTransTable ;
2013-03-29 21:21:27 +01:00
static RECT g_normalRC = { 0 } ;
2013-09-13 15:17:55 -04:00
static std : : wstring windowTitle ;
2013-06-22 22:27:59 +02:00
extern bool g_TakeScreenshot ;
2013-03-29 18:50:08 +01:00
extern InputState input_state ;
2013-07-07 10:42:39 +02:00
2013-05-04 23:21:06 +02:00
# define TIMER_CURSORUPDATE 1
2013-06-12 02:14:53 +08:00
# define TIMER_CURSORMOVEUPDATE 2
2013-10-16 17:20:32 +02:00
# define CURSORUPDATE_INTERVAL_MS 1000
2013-06-12 02:14:53 +08:00
# define CURSORUPDATE_MOVE_TIMESPAN_MS 500
2013-04-18 17:13:00 +08:00
2014-06-29 22:13:53 +02:00
namespace MainWindow
{
2012-11-01 16:19:01 +01:00
HWND hwndMain ;
2014-06-29 22:13:53 +02:00
HWND hwndDisplay ;
HWND hwndGameList ;
2014-01-19 22:54:49 +01:00
TouchInputHandler touchHandler ;
2013-03-29 21:21:27 +01:00
static HMENU menu ;
2012-11-01 16:19:01 +01:00
2013-03-29 21:21:27 +01:00
static HINSTANCE hInst ;
2013-05-26 14:55:23 -07:00
static int cursorCounter = 0 ;
2013-06-12 02:14:53 +08:00
static int prevCursorX = - 1 ;
static int prevCursorY = - 1 ;
static bool mouseButtonDown = false ;
static bool hideCursor = false ;
2013-09-01 14:06:24 -07:00
static std : : map < int , std : : string > initialMenuKeys ;
2013-09-03 22:06:05 -04:00
static std : : vector < std : : string > countryCodes ;
2013-10-12 00:14:58 -04:00
static std : : vector < std : : string > availableShaders ;
2014-01-19 18:44:41 -08:00
static W32Util : : AsyncBrowseDialog * browseDialog ;
static bool browsePauseAfter ;
2014-06-29 21:03:24 +02:00
static bool g_inModeSwitch ; // when true, don't react to WM_SIZE
2014-07-29 18:18:57 -04:00
static int g_WindowState ;
2014-06-29 21:03:24 +02:00
2012-11-01 16:19:01 +01:00
# define MAX_LOADSTRING 100
2013-03-29 21:21:27 +01:00
const TCHAR * szTitle = TEXT ( " PPSSPP " ) ;
const TCHAR * szWindowClass = TEXT ( " PPSSPPWnd " ) ;
const TCHAR * szDisplayClass = TEXT ( " PPSSPPDisplay " ) ;
2012-11-01 16:19:01 +01:00
2013-03-17 14:46:39 +01:00
// Forward declarations of functions included in this code module:
2012-11-01 16:19:01 +01:00
LRESULT CALLBACK WndProc ( HWND , UINT , WPARAM , LPARAM ) ;
2014-06-29 22:13:53 +02:00
LRESULT CALLBACK DisplayProc ( HWND , UINT , WPARAM , LPARAM ) ;
2012-11-01 16:19:01 +01:00
LRESULT CALLBACK About ( HWND , UINT , WPARAM , LPARAM ) ;
2013-07-06 19:12:06 -07:00
HWND GetHWND ( ) {
2012-11-01 16:19:01 +01:00
return hwndMain ;
}
2014-06-29 22:13:53 +02:00
HWND GetDisplayHWND ( ) {
return hwndDisplay ;
}
2013-07-06 19:12:06 -07:00
void Init ( HINSTANCE hInstance ) {
2013-02-19 01:28:13 +01:00
# ifdef THEMES
WTL : : CTheme : : IsThemingSupported ( ) ;
2012-11-01 16:19:01 +01:00
# endif
//Register classes
WNDCLASSEX wcex ;
wcex . cbSize = sizeof ( WNDCLASSEX ) ;
2014-06-23 20:04:31 +02:00
wcex . style = CS_PARENTDC ;
2012-11-01 16:19:01 +01:00
wcex . lpfnWndProc = ( WNDPROC ) WndProc ;
wcex . cbClsExtra = 0 ;
wcex . cbWndExtra = 0 ;
wcex . hInstance = hInstance ;
wcex . hIcon = LoadIcon ( hInstance , ( LPCTSTR ) IDI_PPSSPP ) ;
wcex . hCursor = LoadCursor ( NULL , IDC_ARROW ) ;
2012-12-05 14:31:41 +08:00
wcex . hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
2013-08-26 19:00:16 +02:00
wcex . lpszMenuName = ( LPCWSTR ) IDR_MENU1 ;
2012-11-01 16:19:01 +01:00
wcex . lpszClassName = szWindowClass ;
2014-06-23 20:04:31 +02:00
wcex . hIconSm = ( HICON ) LoadImage ( hInstance , ( LPCTSTR ) IDI_PPSSPP , IMAGE_ICON , 16 , 16 , LR_SHARED ) ;
2012-11-01 16:19:01 +01:00
RegisterClassEx ( & wcex ) ;
2014-06-29 22:13:53 +02:00
wcex . style = CS_HREDRAW | CS_VREDRAW ;
wcex . lpfnWndProc = ( WNDPROC ) DisplayProc ;
wcex . hIcon = 0 ;
wcex . hbrBackground = ( HBRUSH ) GetStockObject ( BLACK_BRUSH ) ;
wcex . lpszMenuName = 0 ;
wcex . lpszClassName = szDisplayClass ;
wcex . hIconSm = 0 ;
RegisterClassEx ( & wcex ) ;
2012-11-01 16:19:01 +01:00
}
2013-03-30 17:49:02 +01:00
void SavePosition ( ) {
2014-06-23 20:04:31 +02:00
if ( g_Config . bFullScreen )
return ;
2013-09-13 11:39:40 -04:00
2013-03-30 17:49:02 +01:00
WINDOWPLACEMENT placement ;
GetWindowPlacement ( hwndMain , & placement ) ;
if ( placement . showCmd = = SW_SHOWNORMAL ) {
RECT rc ;
GetWindowRect ( hwndMain , & rc ) ;
g_Config . iWindowX = rc . left ;
g_Config . iWindowY = rc . top ;
2013-09-11 00:19:34 +02:00
g_Config . iWindowWidth = rc . right - rc . left ;
g_Config . iWindowHeight = rc . bottom - rc . top ;
2013-03-30 17:49:02 +01:00
}
}
2014-02-12 10:36:40 +01:00
static void GetWindowRectAtResolution ( int xres , int yres , RECT & rcInner , RECT & rcOuter ) {
2013-09-11 00:19:34 +02:00
rcInner . left = 0 ;
rcInner . top = 0 ;
rcInner . right = xres ;
rcInner . bottom = yres ;
rcOuter = rcInner ;
AdjustWindowRect ( & rcOuter , WS_OVERLAPPEDWINDOW , TRUE ) ;
rcOuter . right + = g_Config . iWindowX - rcOuter . left ;
rcOuter . bottom + = g_Config . iWindowY - rcOuter . top ;
rcOuter . left = g_Config . iWindowX ;
rcOuter . top = g_Config . iWindowY ;
}
2014-02-12 10:36:40 +01:00
static void ShowScreenResolution ( ) {
2015-07-01 23:50:16 +02:00
I18NCategory * gr = GetI18NCategory ( " Graphics " ) ;
2014-07-10 03:19:00 -04:00
std : : ostringstream messageStream ;
2015-07-01 23:50:16 +02:00
messageStream < < gr - > T ( " Internal Resolution " ) < < " : " ;
2014-07-10 03:19:00 -04:00
messageStream < < PSP_CoreParameter ( ) . renderWidth < < " x " < < PSP_CoreParameter ( ) . renderHeight < < " " ;
2015-07-01 23:50:16 +02:00
messageStream < < gr - > T ( " Window Size " ) < < " : " ;
2014-07-10 03:19:00 -04:00
messageStream < < PSP_CoreParameter ( ) . pixelWidth < < " x " < < PSP_CoreParameter ( ) . pixelHeight ;
osm . Show ( messageStream . str ( ) , 2.0f ) ;
2014-02-12 10:36:40 +01:00
}
2014-02-12 11:34:29 +01:00
static void UpdateRenderResolution ( ) {
2013-01-26 23:46:02 +01:00
RECT rc ;
GetClientRect ( hwndMain , & rc ) ;
2015-05-15 18:04:05 +02:00
// Actually, auto mode should be more granular...
2013-07-29 04:46:40 -04:00
// Round up to a zoom factor for the render size.
2013-09-11 00:19:34 +02:00
int zoom = g_Config . iInternalResolution ;
2015-05-15 18:04:05 +02:00
if ( zoom = = 0 ) { // auto mode
// Use the longest dimension
if ( g_Config . IsPortrait ( ) ) {
zoom = ( rc . bottom - rc . top + 479 ) / 480 ;
} else {
zoom = ( rc . right - rc . left + 479 ) / 480 ;
}
}
2014-06-24 22:32:38 +02:00
if ( zoom < = 1 )
zoom = 1 ;
2014-01-27 11:46:09 +05:00
2015-05-15 18:04:05 +02:00
if ( g_Config . IsPortrait ( ) ) {
PSP_CoreParameter ( ) . renderWidth = 272 * zoom ;
PSP_CoreParameter ( ) . renderHeight = 480 * zoom ;
2015-05-22 18:15:49 +02:00
} else {
PSP_CoreParameter ( ) . renderWidth = 480 * zoom ;
PSP_CoreParameter ( ) . renderHeight = 272 * zoom ;
2015-05-15 18:04:05 +02:00
}
}
static bool IsWindowSmall ( ) {
return g_Config . IsPortrait ( ) ? ( g_Config . iWindowHeight < 480 + 80 ) : ( g_Config . iWindowWidth < 480 + 80 ) ;
2014-02-12 11:34:29 +01:00
}
static void ResizeDisplay ( bool noWindowMovement = false ) {
2014-06-29 12:53:03 +02:00
AssertCurrentThreadName ( " Main " ) ;
2014-02-12 11:34:29 +01:00
int width = 0 , height = 0 ;
RECT rc ;
GetClientRect ( hwndMain , & rc ) ;
if ( ! noWindowMovement ) {
width = rc . right - rc . left ;
height = rc . bottom - rc . top ;
2015-05-15 18:04:05 +02:00
// Moves the internal window, not the frame. TODO: Get rid of the internal window. Tried before but Intel drivers screw up when minimizing, or something?
2014-06-29 22:13:53 +02:00
MoveWindow ( hwndDisplay , 0 , 0 , width , height , TRUE ) ;
2014-02-12 11:34:29 +01:00
// This is taken care of anyway later, but makes sure that ShowScreenResolution gets the right numbers.
// Need to clean all of this up...
PSP_CoreParameter ( ) . pixelWidth = width ;
PSP_CoreParameter ( ) . pixelHeight = height ;
}
UpdateRenderResolution ( ) ;
2013-09-26 17:46:11 -04:00
2014-02-10 16:22:16 +01:00
if ( ! noWindowMovement ) {
2015-05-15 18:04:05 +02:00
if ( UpdateScreenScale ( width , height , IsWindowSmall ( ) ) ) {
2014-12-28 13:19:19 -08:00
NativeMessageReceived ( " gpu resized " , " " ) ;
}
2014-02-10 16:22:16 +01:00
}
2013-09-11 00:19:34 +02:00
}
void SetWindowSize ( int zoom ) {
2014-06-29 13:11:06 +02:00
AssertCurrentThreadName ( " Main " ) ;
2012-11-17 17:46:05 +01:00
RECT rc , rcOuter ;
2015-05-15 18:04:05 +02:00
// Actually, auto mode should be more granular...
if ( g_Config . IsPortrait ( ) ) {
GetWindowRectAtResolution ( 272 * ( int ) zoom , 480 * ( int ) zoom , rc , rcOuter ) ;
} else {
GetWindowRectAtResolution ( 480 * ( int ) zoom , 272 * ( int ) zoom , rc , rcOuter ) ;
}
2012-11-17 17:46:05 +01:00
MoveWindow ( hwndMain , rcOuter . left , rcOuter . top , rcOuter . right - rcOuter . left , rcOuter . bottom - rcOuter . top , TRUE ) ;
2014-02-12 11:34:29 +01:00
ResizeDisplay ( false ) ;
2014-02-12 10:36:40 +01:00
ShowScreenResolution ( ) ;
2012-11-01 16:19:01 +01:00
}
2013-09-19 14:32:56 -04:00
void SetInternalResolution ( int res = - 1 ) {
2013-09-19 21:18:26 -04:00
if ( res > = 0 & & res < = RESOLUTION_MAX )
2013-09-19 14:32:56 -04:00
g_Config . iInternalResolution = res ;
else {
2013-09-19 21:18:26 -04:00
if ( + + g_Config . iInternalResolution > RESOLUTION_MAX )
2013-09-19 14:32:56 -04:00
g_Config . iInternalResolution = 0 ;
}
2013-10-11 11:49:45 +05:00
2014-01-26 18:59:40 +05:00
// Taking auto-texture scaling into account
2013-10-11 11:49:45 +05:00
if ( g_Config . iTexScalingLevel = = TEXSCALING_AUTO )
setTexScalingMultiplier ( 0 ) ;
2013-09-19 14:32:56 -04:00
2014-02-13 16:23:16 -05:00
if ( gpu )
gpu - > Resized ( ) ;
2014-02-12 11:34:29 +01:00
UpdateRenderResolution ( ) ;
2014-02-12 10:36:40 +01:00
ShowScreenResolution ( ) ;
2013-09-11 00:19:34 +02:00
}
2013-05-26 14:55:23 -07:00
void CorrectCursor ( ) {
2014-06-22 09:38:46 +02:00
bool autoHide = g_Config . bFullScreen & & ! mouseButtonDown & & GetUIState ( ) = = UISTATE_INGAME ;
2013-06-12 02:14:53 +08:00
if ( autoHide & & hideCursor ) {
2013-05-26 14:55:23 -07:00
while ( cursorCounter > = 0 ) {
cursorCounter = ShowCursor ( FALSE ) ;
}
} else {
2013-06-12 02:14:53 +08:00
hideCursor = ! autoHide ;
2013-05-26 14:55:23 -07:00
if ( cursorCounter < 0 ) {
cursorCounter = ShowCursor ( TRUE ) ;
SetCursor ( LoadCursor ( NULL , IDC_ARROW ) ) ;
}
}
}
2015-02-15 23:07:24 +01:00
void ToggleFullscreen ( HWND hWnd , bool goingFullscreen ) {
2014-06-29 21:03:24 +02:00
// Make sure no rendering is happening during the switch.
Core_NotifyWindowHidden ( true ) ;
g_inModeSwitch = true ; // Make sure WM_SIZE doesn't call Core_NotifyWindowHidden(false)...
2014-07-16 23:50:46 -04:00
DWORD dwOldStyle ;
DWORD dwNewStyle ;
2013-09-11 00:19:34 +02:00
2014-07-16 23:50:46 -04:00
if ( ! goingFullscreen ) {
// Put caption and border styles back.
dwOldStyle = : : GetWindowLong ( hWnd , GWL_STYLE ) ;
2014-07-20 17:28:25 +02:00
dwOldStyle & = ~ WS_POPUP ;
2014-07-16 23:50:46 -04:00
dwNewStyle = dwOldStyle | WS_CAPTION | WS_THICKFRAME | WS_SYSMENU ;
// Put back the menu bar.
: : SetMenu ( hWnd , menu ) ;
} else {
2014-07-29 18:18:57 -04:00
// If the window was maximized before going fullscreen, make sure to restore first
// in order not to have the taskbar show up on top of PPSSPP.
if ( g_WindowState = = SIZE_MAXIMIZED ) {
ShowWindow ( hwndMain , SW_RESTORE ) ;
}
2014-07-16 23:50:46 -04:00
// Remember the normal window rectangle.
: : GetWindowRect ( hWnd , & g_normalRC ) ;
2013-09-27 15:34:13 -04:00
2014-07-16 23:50:46 -04:00
// Remove caption and border styles.
dwOldStyle = : : GetWindowLong ( hWnd , GWL_STYLE ) ;
dwNewStyle = dwOldStyle & ~ ( WS_CAPTION | WS_THICKFRAME | WS_SYSMENU ) ;
2014-07-20 17:28:25 +02:00
// Add WS_POPUP
dwNewStyle | = WS_POPUP ;
2014-02-12 10:36:40 +01:00
}
2014-06-29 21:03:24 +02:00
2013-09-11 00:19:34 +02:00
: : SetWindowLong ( hWnd , GWL_STYLE , dwNewStyle ) ;
// Remove the menu bar.
2014-07-17 00:03:41 -04:00
: : SetMenu ( hWnd , goingFullscreen ? NULL : menu ) ;
2013-09-11 00:19:34 +02:00
2014-07-17 00:06:52 -04:00
// Resize to the appropriate view.
2014-07-29 18:18:57 -04:00
// If we're returning to window mode, re-apply the appropriate size setting.
if ( goingFullscreen ) {
ShowWindow ( hwndMain , SW_MAXIMIZE ) ;
} else {
ShowWindow ( hwndMain , g_WindowState = = SIZE_MAXIMIZED ? SW_MAXIMIZE : SW_RESTORE ) ;
}
2013-09-11 00:19:34 +02:00
2014-07-16 23:50:46 -04:00
g_Config . bFullScreen = goingFullscreen ;
2013-09-11 00:19:34 +02:00
CorrectCursor ( ) ;
2013-09-27 15:34:13 -04:00
bool showOSM = ( g_Config . iInternalResolution = = RESOLUTION_AUTO ) ;
2014-06-29 21:03:24 +02:00
ResizeDisplay ( false ) ;
2014-02-12 10:36:40 +01:00
if ( showOSM ) {
ShowScreenResolution ( ) ;
}
2014-07-17 00:03:41 -04:00
ShowOwnedPopups ( hwndMain , goingFullscreen ? FALSE : TRUE ) ;
2014-07-16 23:50:46 -04:00
W32Util : : MakeTopMost ( hwndMain , g_Config . bTopMost ) ;
2014-06-29 21:03:24 +02:00
g_inModeSwitch = false ;
Core_NotifyWindowHidden ( false ) ;
2015-02-15 23:07:24 +01:00
WindowsRawInput : : NotifyMenu ( ) ;
2013-09-11 00:19:34 +02:00
}
2013-10-15 13:10:14 +02:00
RECT DetermineWindowRectangle ( ) {
RECT rc ;
const int screenWidth = GetSystemMetrics ( SM_CXVIRTUALSCREEN ) ;
const int screenHeight = GetSystemMetrics ( SM_CYVIRTUALSCREEN ) ;
const int screenX = GetSystemMetrics ( SM_XVIRTUALSCREEN ) ;
const int screenY = GetSystemMetrics ( SM_YVIRTUALSCREEN ) ;
if ( ! g_Config . bFullScreen ) {
bool visibleHorizontally = ( ( g_Config . iWindowX + g_Config . iWindowWidth ) > = screenX ) & &
( ( g_Config . iWindowX + g_Config . iWindowWidth ) < ( screenWidth + g_Config . iWindowWidth ) ) ;
bool visibleVertically = ( ( g_Config . iWindowY + g_Config . iWindowHeight ) > = screenY ) & &
( ( g_Config . iWindowY + g_Config . iWindowHeight ) < ( screenHeight + g_Config . iWindowHeight ) ) ;
if ( ! visibleHorizontally )
g_Config . iWindowX = - 1 ;
if ( ! visibleVertically )
g_Config . iWindowY = - 1 ;
}
rc . left = g_Config . iWindowX ;
rc . top = g_Config . iWindowY ;
// First, get the w/h right.
if ( g_Config . iWindowWidth < = 0 | | g_Config . iWindowHeight < = 0 ) {
RECT rcInner = rc , rcOuter ;
2015-05-15 18:04:05 +02:00
bool portrait = g_Config . IsPortrait ( ) ;
GetWindowRectAtResolution ( 2 * ( portrait ? 272 : 480 ) , 2 * ( portrait ? 480 : 272 ) , rcInner , rcOuter ) ;
2013-10-15 13:10:14 +02:00
rc . right = rc . left + ( rcOuter . right - rcOuter . left ) ;
rc . bottom = rc . top + ( rcOuter . bottom - rcOuter . top ) ;
g_Config . iWindowWidth = rc . right - rc . left ;
g_Config . iWindowHeight = rc . bottom - rc . top ;
} else {
rc . right = rc . left + g_Config . iWindowWidth ;
rc . bottom = rc . top + g_Config . iWindowHeight ;
}
// Then center if necessary.
if ( g_Config . iWindowX = = - 1 & & g_Config . iWindowY = = - 1 ) {
// Center the window.
2013-10-15 22:02:14 -07:00
const int primaryScreenWidth = GetSystemMetrics ( SM_CXSCREEN ) ;
const int primaryScreenHeight = GetSystemMetrics ( SM_CYSCREEN ) ;
g_Config . iWindowX = ( primaryScreenWidth - g_Config . iWindowWidth ) / 2 ;
g_Config . iWindowY = ( primaryScreenHeight - g_Config . iWindowHeight ) / 2 ;
2013-10-15 13:10:14 +02:00
rc . left = g_Config . iWindowX ;
rc . top = g_Config . iWindowY ;
rc . right = rc . left + g_Config . iWindowWidth ;
rc . bottom = rc . top + g_Config . iWindowHeight ;
}
return rc ;
}
2013-09-16 18:08:09 -04:00
void SetIngameMenuItemStates ( const GlobalUIState state ) {
UINT menuEnable = state = = UISTATE_INGAME ? MF_ENABLED : MF_GRAYED ;
2013-11-27 21:57:17 +08:00
UINT umdSwitchEnable = state = = UISTATE_INGAME & & getUMDReplacePermit ( ) ? MF_ENABLED : MF_GRAYED ;
2013-09-16 18:08:09 -04:00
EnableMenuItem ( menu , ID_FILE_SAVESTATEFILE , menuEnable ) ;
EnableMenuItem ( menu , ID_FILE_LOADSTATEFILE , menuEnable ) ;
EnableMenuItem ( menu , ID_FILE_QUICKSAVESTATE , menuEnable ) ;
EnableMenuItem ( menu , ID_FILE_QUICKLOADSTATE , menuEnable ) ;
EnableMenuItem ( menu , ID_TOGGLE_PAUSE , menuEnable ) ;
EnableMenuItem ( menu , ID_EMULATION_STOP , menuEnable ) ;
EnableMenuItem ( menu , ID_EMULATION_RESET , menuEnable ) ;
2013-11-27 21:57:17 +08:00
EnableMenuItem ( menu , ID_EMULATION_SWITCH_UMD , umdSwitchEnable ) ;
2014-03-01 11:25:40 -08:00
EnableMenuItem ( menu , ID_DEBUG_LOADMAPFILE , menuEnable ) ;
EnableMenuItem ( menu , ID_DEBUG_SAVEMAPFILE , menuEnable ) ;
2014-06-30 00:02:22 +02:00
EnableMenuItem ( menu , ID_DEBUG_LOADSYMFILE , menuEnable ) ;
EnableMenuItem ( menu , ID_DEBUG_SAVESYMFILE , menuEnable ) ;
2014-03-01 11:25:40 -08:00
EnableMenuItem ( menu , ID_DEBUG_RESETSYMBOLTABLE , menuEnable ) ;
EnableMenuItem ( menu , ID_DEBUG_EXTRACTFILE , menuEnable ) ;
2013-09-16 18:08:09 -04:00
}
2013-09-11 00:19:34 +02:00
2013-09-04 08:41:57 -04:00
// These are used as an offset
// to determine which menu item to change.
// Make sure to count(from 0) the separators too, when dealing with submenus!!
2013-09-16 18:08:09 -04:00
enum MenuItemPosition {
2013-09-04 08:41:57 -04:00
// Main menus
MENU_FILE = 0 ,
MENU_EMULATION = 1 ,
MENU_DEBUG = 2 ,
MENU_OPTIONS = 3 ,
2013-11-02 20:24:19 -04:00
MENU_HELP = 4 ,
2013-09-04 08:41:57 -04:00
2013-09-07 11:29:44 -04:00
// File submenus
SUBMENU_FILE_SAVESTATE_SLOT = 6 ,
2013-09-04 08:41:57 -04:00
// Game Settings submenus
2014-01-09 21:15:46 +08:00
SUBMENU_CUSTOM_SHADERS = 10 ,
SUBMENU_RENDERING_RESOLUTION = 11 ,
SUBMENU_WINDOW_SIZE = 12 ,
2014-09-14 07:30:49 -04:00
SUBMENU_RENDERING_BACKEND = 13 ,
SUBMENU_RENDERING_MODE = 14 ,
SUBMENU_FRAME_SKIPPING = 15 ,
SUBMENU_TEXTURE_FILTERING = 16 ,
SUBMENU_BUFFER_FILTER = 17 ,
SUBMENU_TEXTURE_SCALING = 18 ,
2013-09-04 08:41:57 -04:00
} ;
2013-08-29 16:13:22 -04:00
std : : string GetMenuItemText ( int menuID ) {
MENUITEMINFO menuInfo ;
2013-08-30 15:27:16 +02:00
memset ( & menuInfo , 0 , sizeof ( menuInfo ) ) ;
2013-08-29 16:13:22 -04:00
menuInfo . cbSize = sizeof ( MENUITEMINFO ) ;
menuInfo . fMask = MIIM_STRING ;
menuInfo . dwTypeData = 0 ;
2013-08-30 22:18:37 -07:00
std : : string retVal ;
if ( GetMenuItemInfo ( menu , menuID , MF_BYCOMMAND , & menuInfo ) ! = FALSE ) {
wchar_t * buffer = new wchar_t [ + + menuInfo . cch ] ;
menuInfo . dwTypeData = buffer ;
GetMenuItemInfo ( menu , menuID , MF_BYCOMMAND , & menuInfo ) ;
retVal = ConvertWStringToUTF8 ( menuInfo . dwTypeData ) ;
delete [ ] buffer ;
}
2013-08-29 16:13:22 -04:00
return retVal ;
}
2013-09-01 14:06:24 -07:00
const std : : string & GetMenuItemInitialText ( const int menuID ) {
if ( initialMenuKeys . find ( menuID ) = = initialMenuKeys . end ( ) ) {
initialMenuKeys [ menuID ] = GetMenuItemText ( menuID ) ;
}
return initialMenuKeys [ menuID ] ;
}
2013-09-04 10:45:48 -04:00
void CreateHelpMenu ( ) {
2013-09-16 18:55:06 -04:00
I18NCategory * des = GetI18NCategory ( " DesktopUI " ) ;
2013-09-04 10:45:48 -04:00
2013-09-16 18:55:06 -04:00
const std : : wstring help = ConvertUTF8ToWString ( des - > T ( " Help " ) ) ;
const std : : wstring visitMainWebsite = ConvertUTF8ToWString ( des - > T ( " www.ppsspp.org " ) ) ;
const std : : wstring visitForum = ConvertUTF8ToWString ( des - > T ( " PPSSPP Forums " ) ) ;
const std : : wstring buyGold = ConvertUTF8ToWString ( des - > T ( " Buy Gold " ) ) ;
const std : : wstring aboutPPSSPP = ConvertUTF8ToWString ( des - > T ( " About PPSSPP... " ) ) ;
2013-09-04 10:45:48 -04:00
// Simply remove the old help menu and create a new one.
RemoveMenu ( menu , MENU_HELP , MF_BYPOSITION ) ;
2013-09-16 18:08:09 -04:00
HMENU helpMenu = CreatePopupMenu ( ) ;
2013-09-04 10:45:48 -04:00
InsertMenu ( menu , MENU_HELP , MF_POPUP | MF_STRING | MF_BYPOSITION , ( UINT_PTR ) helpMenu , help . c_str ( ) ) ;
2013-09-04 11:14:39 -04:00
AppendMenu ( helpMenu , MF_STRING | MF_BYCOMMAND , ID_HELP_OPENWEBSITE , visitMainWebsite . c_str ( ) ) ;
AppendMenu ( helpMenu , MF_STRING | MF_BYCOMMAND , ID_HELP_OPENFORUM , visitForum . c_str ( ) ) ;
2013-09-04 10:45:48 -04:00
// Repeat the process for other languages, if necessary.
2013-09-04 11:14:39 -04:00
AppendMenu ( helpMenu , MF_STRING | MF_BYCOMMAND , ID_HELP_BUYGOLD , buyGold . c_str ( ) ) ;
2013-09-04 10:45:48 -04:00
AppendMenu ( helpMenu , MF_SEPARATOR , 0 , 0 ) ;
2013-09-04 11:14:39 -04:00
AppendMenu ( helpMenu , MF_STRING | MF_BYCOMMAND , ID_HELP_ABOUT , aboutPPSSPP . c_str ( ) ) ;
2013-09-04 10:45:48 -04:00
}
2013-10-12 01:15:47 -04:00
void UpdateDynamicMenuCheckmarks ( ) {
int item = ID_SHADERS_BASE + 1 ;
2013-10-12 16:49:22 -07:00
for ( size_t i = 0 ; i < availableShaders . size ( ) ; i + + )
2013-10-12 01:15:47 -04:00
CheckMenuItem ( menu , item + + , ( ( g_Config . sPostShaderName = = availableShaders [ i ] ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
}
2013-10-12 00:14:58 -04:00
void CreateShadersSubmenu ( ) {
2013-10-12 00:22:59 -04:00
I18NCategory * des = GetI18NCategory ( " DesktopUI " ) ;
2013-11-30 00:37:15 -05:00
I18NCategory * ps = GetI18NCategory ( " PostShaders " ) ;
2013-10-12 00:22:59 -04:00
const std : : wstring key = ConvertUTF8ToWString ( des - > T ( " Postprocessing Shader " ) ) ;
2013-10-12 00:14:58 -04:00
HMENU optionsMenu = GetSubMenu ( menu , MENU_OPTIONS ) ;
2013-10-12 00:22:59 -04:00
HMENU shaderMenu = CreatePopupMenu ( ) ;
RemoveMenu ( optionsMenu , SUBMENU_CUSTOM_SHADERS , MF_BYPOSITION ) ;
2013-10-12 00:14:58 -04:00
InsertMenu ( optionsMenu , SUBMENU_CUSTOM_SHADERS , MF_POPUP | MF_STRING | MF_BYPOSITION , ( UINT_PTR ) shaderMenu , key . c_str ( ) ) ;
std : : vector < ShaderInfo > info = GetAllPostShaderInfo ( ) ;
availableShaders . clear ( ) ;
2013-10-12 01:15:47 -04:00
2013-10-12 00:22:59 -04:00
int item = ID_SHADERS_BASE + 1 ;
2013-10-12 01:15:47 -04:00
int checkedStatus = - 1 ;
2013-11-29 12:51:24 -05:00
const char * translatedShaderName = nullptr ;
2013-10-12 00:14:58 -04:00
for ( auto i = info . begin ( ) ; i ! = info . end ( ) ; + + i ) {
2013-10-12 01:15:47 -04:00
checkedStatus = MF_UNCHECKED ;
2013-10-12 00:14:58 -04:00
availableShaders . push_back ( i - > section ) ;
2013-10-12 01:15:47 -04:00
if ( g_Config . sPostShaderName = = i - > section ) {
checkedStatus = MF_CHECKED ;
}
2013-11-30 00:37:15 -05:00
translatedShaderName = ps - > T ( i - > section . c_str ( ) ) ;
2013-11-29 12:51:24 -05:00
AppendMenu ( shaderMenu , MF_STRING | MF_BYPOSITION | checkedStatus , item + + , ConvertUTF8ToWString ( translatedShaderName ) . c_str ( ) ) ;
2013-10-12 00:14:58 -04:00
}
}
2013-09-16 18:08:09 -04:00
void _TranslateMenuItem ( const int menuIDOrPosition , const char * key , bool byCommand = false , const std : : wstring & accelerator = L " " , const HMENU hMenu = menu ) {
2013-09-16 18:55:06 -04:00
I18NCategory * des = GetI18NCategory ( " DesktopUI " ) ;
2013-09-13 13:06:13 -04:00
2013-09-16 18:55:06 -04:00
std : : wstring translated = ConvertUTF8ToWString ( des - > T ( key ) ) ;
2013-08-30 17:29:22 -04:00
translated . append ( accelerator ) ;
2013-09-16 18:08:09 -04:00
u32 flags = MF_STRING | ( byCommand ? MF_BYCOMMAND : MF_BYPOSITION ) ;
2013-09-13 13:06:13 -04:00
2013-09-16 18:08:09 -04:00
ModifyMenu ( hMenu , menuIDOrPosition , flags , menuIDOrPosition , translated . c_str ( ) ) ;
2013-09-13 13:06:13 -04:00
}
2013-09-16 18:08:09 -04:00
void TranslateMenuItem ( const int menuID , const std : : wstring & accelerator = L " " , const char * key = " " , const HMENU hMenu = menu ) {
if ( key = = nullptr | | ! strcmp ( key , " " ) )
_TranslateMenuItem ( menuID , GetMenuItemInitialText ( menuID ) . c_str ( ) , true , accelerator , hMenu ) ;
2013-09-13 13:06:13 -04:00
else
2013-09-16 18:08:09 -04:00
_TranslateMenuItem ( menuID , key , true , accelerator , hMenu ) ;
2013-09-13 13:06:13 -04:00
}
2013-09-16 18:08:09 -04:00
void TranslateMenu ( const char * key , const MenuItemPosition mainMenuPosition , const std : : wstring & accelerator = L " " ) {
_TranslateMenuItem ( mainMenuPosition , key , false , accelerator ) ;
2013-08-30 17:29:22 -04:00
}
2013-09-16 18:08:09 -04:00
void TranslateSubMenu ( const char * key , const MenuItemPosition mainMenuItem , const MenuItemPosition subMenuItem , const std : : wstring & accelerator = L " " ) {
_TranslateMenuItem ( subMenuItem , key , false , accelerator , GetSubMenu ( menu , mainMenuItem ) ) ;
2013-08-29 16:13:22 -04:00
}
void TranslateMenus ( ) {
2013-09-16 18:08:09 -04:00
// Menu headers and submenu headers don't have resource IDs,
// So we have to hardcode strings here, unfortunately.
TranslateMenu ( " File " , MENU_FILE ) ;
TranslateMenu ( " Emulation " , MENU_EMULATION ) ;
TranslateMenu ( " Debugging " , MENU_DEBUG ) ;
TranslateMenu ( " Game Settings " , MENU_OPTIONS ) ;
TranslateMenu ( " Help " , MENU_HELP ) ;
2013-08-29 16:13:22 -04:00
2013-10-12 00:22:59 -04:00
CreateShadersSubmenu ( ) ;
2013-08-29 16:13:22 -04:00
// File menu
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_FILE_LOAD ) ;
TranslateMenuItem ( ID_FILE_LOAD_DIR ) ;
TranslateMenuItem ( ID_FILE_LOAD_MEMSTICK ) ;
TranslateMenuItem ( ID_FILE_MEMSTICK ) ;
2014-06-04 22:09:04 +03:00
TranslateSubMenu ( " Savestate Slot " , MENU_FILE , SUBMENU_FILE_SAVESTATE_SLOT , L " \t F3 " ) ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_FILE_QUICKLOADSTATE , L " \t F4 " ) ;
TranslateMenuItem ( ID_FILE_QUICKSAVESTATE , L " \t F2 " ) ;
TranslateMenuItem ( ID_FILE_LOADSTATEFILE ) ;
TranslateMenuItem ( ID_FILE_SAVESTATEFILE ) ;
TranslateMenuItem ( ID_FILE_EXIT , L " \t Alt+F4 " ) ;
2013-08-29 16:13:22 -04:00
// Emulation menu
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_TOGGLE_PAUSE , L " \t F8 " , " Pause " ) ;
TranslateMenuItem ( ID_EMULATION_STOP , L " \t Ctrl+W " ) ;
2013-11-27 21:57:17 +08:00
TranslateMenuItem ( ID_EMULATION_RESET , L " \t Ctrl+B " ) ;
TranslateMenuItem ( ID_EMULATION_SWITCH_UMD , L " \t Ctrl+U " , " Switch UMD " ) ;
2013-09-03 22:06:05 -04:00
2013-08-29 16:13:22 -04:00
// Debug menu
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_DEBUG_LOADMAPFILE ) ;
TranslateMenuItem ( ID_DEBUG_SAVEMAPFILE ) ;
2014-06-30 00:02:22 +02:00
TranslateMenuItem ( ID_DEBUG_LOADSYMFILE ) ;
TranslateMenuItem ( ID_DEBUG_SAVESYMFILE ) ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_DEBUG_RESETSYMBOLTABLE ) ;
TranslateMenuItem ( ID_DEBUG_DUMPNEXTFRAME ) ;
TranslateMenuItem ( ID_DEBUG_TAKESCREENSHOT , L " \t F12 " ) ;
TranslateMenuItem ( ID_DEBUG_SHOWDEBUGSTATISTICS ) ;
TranslateMenuItem ( ID_DEBUG_IGNOREILLEGALREADS ) ;
TranslateMenuItem ( ID_DEBUG_RUNONLOAD ) ;
TranslateMenuItem ( ID_DEBUG_DISASSEMBLY , L " \t Ctrl+D " ) ;
2013-09-30 15:56:08 +02:00
TranslateMenuItem ( ID_DEBUG_GEDEBUGGER , L " \t Ctrl+G " ) ;
2014-01-04 12:33:02 +01:00
TranslateMenuItem ( ID_DEBUG_EXTRACTFILE ) ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_DEBUG_LOG , L " \t Ctrl+L " ) ;
TranslateMenuItem ( ID_DEBUG_MEMORYVIEW , L " \t Ctrl+M " ) ;
2013-08-29 16:13:22 -04:00
// Options menu
2013-11-02 20:24:19 -04:00
TranslateMenuItem ( ID_OPTIONS_LANGUAGE ) ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_OPTIONS_TOPMOST ) ;
2013-10-11 14:53:25 +03:00
TranslateMenuItem ( ID_OPTIONS_PAUSE_FOCUS ) ;
2014-01-07 16:08:11 -05:00
TranslateMenuItem ( ID_OPTIONS_IGNOREWINKEY ) ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_OPTIONS_MORE_SETTINGS ) ;
TranslateMenuItem ( ID_OPTIONS_CONTROLS ) ;
TranslateMenuItem ( ID_OPTIONS_STRETCHDISPLAY ) ;
TranslateMenuItem ( ID_OPTIONS_FULLSCREEN , L " \t Alt+Return, F11 " ) ;
TranslateMenuItem ( ID_OPTIONS_VSYNC ) ;
2013-10-12 00:22:59 -04:00
TranslateSubMenu ( " Postprocessing Shader " , MENU_OPTIONS , SUBMENU_CUSTOM_SHADERS ) ;
2013-09-16 18:08:09 -04:00
TranslateSubMenu ( " Rendering Resolution " , MENU_OPTIONS , SUBMENU_RENDERING_RESOLUTION , L " \t Ctrl+1 " ) ;
TranslateMenuItem ( ID_OPTIONS_SCREENAUTO ) ;
2013-09-11 10:20:14 +08:00
// Skip rendering resolution 2x-5x..
2013-09-16 18:08:09 -04:00
TranslateSubMenu ( " Window Size " , MENU_OPTIONS , SUBMENU_WINDOW_SIZE ) ;
2013-09-11 10:20:14 +08:00
// Skip window size 1x-4x..
2014-09-14 07:30:49 -04:00
TranslateSubMenu ( " Backend " , MENU_OPTIONS , SUBMENU_RENDERING_BACKEND ) ;
TranslateMenuItem ( ID_OPTIONS_DIRECTX ) ;
TranslateMenuItem ( ID_OPTIONS_OPENGL ) ;
2013-09-16 18:08:09 -04:00
TranslateSubMenu ( " Rendering Mode " , MENU_OPTIONS , SUBMENU_RENDERING_MODE , L " \t F5 " ) ;
TranslateMenuItem ( ID_OPTIONS_NONBUFFEREDRENDERING ) ;
TranslateMenuItem ( ID_OPTIONS_BUFFEREDRENDERING ) ;
TranslateMenuItem ( ID_OPTIONS_READFBOTOMEMORYCPU ) ;
TranslateMenuItem ( ID_OPTIONS_READFBOTOMEMORYGPU ) ;
TranslateSubMenu ( " Frame Skipping " , MENU_OPTIONS , SUBMENU_FRAME_SKIPPING , L " \t F7 " ) ;
TranslateMenuItem ( ID_OPTIONS_FRAMESKIP_AUTO ) ;
2014-01-25 21:41:39 +05:00
TranslateMenuItem ( ID_OPTIONS_FRAMESKIP_0 ) ;
2013-09-11 10:20:14 +08:00
// Skip frameskipping 1-8..
2013-09-16 18:08:09 -04:00
TranslateSubMenu ( " Texture Filtering " , MENU_OPTIONS , SUBMENU_TEXTURE_FILTERING ) ;
TranslateMenuItem ( ID_OPTIONS_TEXTUREFILTERING_AUTO ) ;
TranslateMenuItem ( ID_OPTIONS_NEARESTFILTERING ) ;
TranslateMenuItem ( ID_OPTIONS_LINEARFILTERING ) ;
TranslateMenuItem ( ID_OPTIONS_LINEARFILTERING_CG ) ;
2014-08-08 20:51:15 +02:00
TranslateSubMenu ( " Screen Scaling Filter " , MENU_OPTIONS , SUBMENU_BUFFER_FILTER ) ;
TranslateMenuItem ( ID_OPTIONS_BUFLINEARFILTER ) ;
TranslateMenuItem ( ID_OPTIONS_BUFNEARESTFILTER ) ;
2013-09-16 18:08:09 -04:00
TranslateSubMenu ( " Texture Scaling " , MENU_OPTIONS , SUBMENU_TEXTURE_SCALING ) ;
TranslateMenuItem ( ID_TEXTURESCALING_OFF ) ;
2013-08-29 17:35:01 -04:00
// Skip texture scaling 2x-5x...
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_TEXTURESCALING_XBRZ ) ;
TranslateMenuItem ( ID_TEXTURESCALING_HYBRID ) ;
TranslateMenuItem ( ID_TEXTURESCALING_BICUBIC ) ;
TranslateMenuItem ( ID_TEXTURESCALING_HYBRID_BICUBIC ) ;
TranslateMenuItem ( ID_TEXTURESCALING_DEPOSTERIZE ) ;
TranslateMenuItem ( ID_OPTIONS_HARDWARETRANSFORM , L " \t F6 " ) ;
TranslateMenuItem ( ID_OPTIONS_VERTEXCACHE ) ;
TranslateMenuItem ( ID_OPTIONS_SHOWFPS ) ;
TranslateMenuItem ( ID_EMULATION_SOUND ) ;
TranslateMenuItem ( ID_EMULATION_CHEATS , L " \t Ctrl+T " ) ;
2013-09-04 10:45:48 -04:00
// Help menu: it's translated in CreateHelpMenu.
CreateHelpMenu ( ) ;
2013-08-29 16:13:22 -04:00
2013-09-16 18:08:09 -04:00
// TODO: Urgh! Why do we need this here?
// The menu is supposed to enable/disable this stuff directly afterward.
2014-06-22 09:38:46 +02:00
SetIngameMenuItemStates ( GetUIState ( ) ) ;
2013-08-29 18:27:11 -04:00
2013-08-29 16:13:22 -04:00
DrawMenuBar ( hwndMain ) ;
2013-09-07 17:22:40 -04:00
UpdateMenus ( ) ;
2013-08-29 16:13:22 -04:00
}
2013-07-29 04:46:40 -04:00
void setTexScalingMultiplier ( int level ) {
2013-07-26 20:25:11 +08:00
g_Config . iTexScalingLevel = level ;
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu clear cache " , " " ) ;
2013-05-01 23:55:34 +02:00
}
2013-06-30 14:48:50 +08:00
2013-07-26 20:25:11 +08:00
void setTexFiltering ( int type ) {
g_Config . iTexFiltering = type ;
2013-06-30 14:48:50 +08:00
}
2014-08-08 20:51:15 +02:00
void setBufFilter ( int type ) {
g_Config . iBufFilter = type ;
}
2013-07-26 20:25:11 +08:00
void setTexScalingType ( int type ) {
g_Config . iTexScalingType = type ;
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu clear cache " , " " ) ;
2013-04-30 03:47:33 +02:00
}
2013-06-30 14:48:50 +08:00
2013-09-19 21:18:26 -04:00
void setRenderingMode ( int mode = - 1 ) {
if ( mode > = FB_NON_BUFFERED_MODE )
g_Config . iRenderingMode = mode ;
else {
if ( + + g_Config . iRenderingMode > FB_READFBOMEMORY_GPU )
g_Config . iRenderingMode = FB_NON_BUFFERED_MODE ;
}
2013-07-29 18:05:08 -04:00
2015-07-01 23:50:16 +02:00
I18NCategory * gr = GetI18NCategory ( " Graphics " ) ;
2013-07-29 18:05:08 -04:00
switch ( g_Config . iRenderingMode ) {
case FB_NON_BUFFERED_MODE :
2015-07-01 23:50:16 +02:00
osm . Show ( gr - > T ( " Non-Buffered Rendering " ) ) ;
2015-02-09 23:10:57 +01:00
g_Config . bAutoFrameSkip = false ;
2013-07-29 18:05:08 -04:00
break ;
case FB_BUFFERED_MODE :
2015-07-01 23:50:16 +02:00
osm . Show ( gr - > T ( " Buffered Rendering " ) ) ;
2013-07-29 18:05:08 -04:00
break ;
case FB_READFBOMEMORY_CPU :
2015-07-01 23:50:16 +02:00
osm . Show ( gr - > T ( " Read Framebuffers To Memory (CPU) " ) ) ;
2013-07-29 18:05:08 -04:00
break ;
case FB_READFBOMEMORY_GPU :
2015-07-01 23:50:16 +02:00
osm . Show ( gr - > T ( " Read Framebuffers To Memory (GPU) " ) ) ;
2013-07-29 18:05:08 -04:00
break ;
}
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu resized " , " " ) ;
2013-07-21 23:17:42 +08:00
}
2013-05-09 19:36:23 -05:00
void setFpsLimit ( int fps ) {
g_Config . iFpsLimit = fps ;
}
2013-06-30 14:48:50 +08:00
2013-09-19 21:18:26 -04:00
void setFrameSkipping ( int framesToSkip = - 1 ) {
if ( framesToSkip > = FRAMESKIP_OFF )
g_Config . iFrameSkip = framesToSkip ;
else {
if ( + + g_Config . iFrameSkip > FRAMESKIP_MAX )
g_Config . iFrameSkip = FRAMESKIP_OFF ;
}
2013-08-21 07:44:08 -04:00
2015-07-01 23:50:16 +02:00
I18NCategory * gr = GetI18NCategory ( " Graphics " ) ;
2013-08-21 13:22:13 -04:00
2014-07-10 03:19:00 -04:00
std : : ostringstream messageStream ;
2015-07-01 23:50:16 +02:00
messageStream < < gr - > T ( " Frame Skipping " ) < < " : " < < " " ;
2013-08-21 13:22:13 -04:00
2014-07-10 03:19:00 -04:00
if ( g_Config . iFrameSkip = = FRAMESKIP_OFF )
2015-07-01 23:50:16 +02:00
messageStream < < gr - > T ( " Off " ) ;
2014-07-10 03:19:00 -04:00
else
messageStream < < g_Config . iFrameSkip ;
2013-08-21 13:35:26 -04:00
2014-07-10 03:19:00 -04:00
osm . Show ( messageStream . str ( ) ) ;
2013-08-21 13:35:26 -04:00
}
2013-07-26 20:25:11 +08:00
2013-07-29 15:34:30 -04:00
void enableCheats ( bool cheats ) {
2013-05-23 13:10:39 +02:00
g_Config . bEnableCheats = cheats ;
2013-05-18 17:04:01 -05:00
}
2013-04-30 03:47:33 +02:00
2013-09-13 15:17:55 -04:00
void UpdateWindowTitle ( ) {
2013-09-13 16:38:28 -04:00
// Seems to be fine to call now since we use a UNICODE build...
SetWindowText ( hwndMain , windowTitle . c_str ( ) ) ;
2013-09-13 15:17:55 -04:00
}
void SetWindowTitle ( const wchar_t * title ) {
windowTitle = title ;
}
2014-07-17 00:06:52 -04:00
BOOL Show ( HINSTANCE hInstance ) {
2013-09-22 14:44:35 -04:00
hInst = hInstance ; // Store instance handle in our global variable.
RECT rc = DetermineWindowRectangle ( ) ;
2013-03-29 21:21:27 +01:00
u32 style = WS_OVERLAPPEDWINDOW ;
2012-11-01 16:19:01 +01:00
2013-08-26 19:00:16 +02:00
hwndMain = CreateWindowEx ( 0 , szWindowClass , L " " , style ,
2013-06-08 08:32:07 +08:00
rc . left , rc . top , rc . right - rc . left , rc . bottom - rc . top , NULL , NULL , hInstance , NULL ) ;
2012-11-01 16:19:01 +01:00
if ( ! hwndMain )
return FALSE ;
2013-09-11 00:19:34 +02:00
RECT rcClient ;
GetClientRect ( hwndMain , & rcClient ) ;
2014-06-29 22:13:53 +02:00
hwndDisplay = CreateWindowEx ( 0 , szDisplayClass , L " " , WS_CHILD | WS_VISIBLE ,
0 , 0 , rcClient . right - rcClient . left , rcClient . bottom - rcClient . top , hwndMain , 0 , hInstance , 0 ) ;
if ( ! hwndDisplay )
return FALSE ;
2012-11-01 16:19:01 +01:00
menu = GetMenu ( hwndMain ) ;
2013-08-29 18:27:11 -04:00
2012-11-01 16:19:01 +01:00
# ifdef FINAL
RemoveMenu ( menu , 2 , MF_BYPOSITION ) ;
RemoveMenu ( menu , 2 , MF_BYPOSITION ) ;
# endif
MENUINFO info ;
ZeroMemory ( & info , sizeof ( MENUINFO ) ) ;
info . cbSize = sizeof ( MENUINFO ) ;
info . cyMax = 0 ;
info . dwStyle = MNS_CHECKORBMP ;
info . fMask = MIM_STYLE ;
2013-07-29 15:34:30 -04:00
for ( int i = 0 ; i < GetMenuItemCount ( menu ) ; i + + ) {
2012-11-01 16:19:01 +01:00
SetMenuInfo ( GetSubMenu ( menu , i ) , & info ) ;
}
2013-06-08 08:32:07 +08:00
UpdateMenus ( ) ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
// Accept dragged files.
2012-11-01 16:19:01 +01:00
DragAcceptFiles ( hwndMain , TRUE ) ;
2013-06-12 02:14:53 +08:00
hideCursor = true ;
2013-06-08 08:32:07 +08:00
SetTimer ( hwndMain , TIMER_CURSORUPDATE , CURSORUPDATE_INTERVAL_MS , 0 ) ;
2014-06-29 16:24:20 -04:00
2014-07-16 23:50:46 -04:00
ToggleFullscreen ( hwndMain , g_Config . bFullScreen ) ;
2013-06-08 08:32:07 +08:00
2013-07-06 13:47:37 -04:00
W32Util : : MakeTopMost ( hwndMain , g_Config . bTopMost ) ;
2014-06-29 22:13:53 +02:00
touchHandler . registerTouchWindow ( hwndDisplay ) ;
2013-04-16 21:12:55 +02:00
2014-01-19 11:59:11 -08:00
WindowsRawInput : : Init ( ) ;
2013-07-07 10:42:39 +02:00
2013-10-16 17:20:32 +02:00
SetFocus ( hwndMain ) ;
2014-03-24 20:13:35 -04:00
2012-11-01 16:19:01 +01:00
return TRUE ;
}
2013-08-26 14:19:46 +02:00
void CreateDebugWindows ( ) {
disasmWindow [ 0 ] = new CDisasm ( MainWindow : : GetHInstance ( ) , MainWindow : : GetHWND ( ) , currentDebugMIPS ) ;
DialogManager : : AddDlg ( disasmWindow [ 0 ] ) ;
disasmWindow [ 0 ] - > Show ( g_Config . bShowDebuggerOnLoad ) ;
2013-09-22 10:27:09 -07:00
geDebuggerWindow = new CGEDebugger ( MainWindow : : GetHInstance ( ) , MainWindow : : GetHWND ( ) ) ;
DialogManager : : AddDlg ( geDebuggerWindow ) ;
2013-08-26 14:19:46 +02:00
memoryWindow [ 0 ] = new CMemoryDlg ( MainWindow : : GetHInstance ( ) , MainWindow : : GetHWND ( ) , currentDebugMIPS ) ;
DialogManager : : AddDlg ( memoryWindow [ 0 ] ) ;
}
2014-02-14 21:17:36 -08:00
void DestroyDebugWindows ( ) {
DialogManager : : RemoveDlg ( disasmWindow [ 0 ] ) ;
if ( disasmWindow [ 0 ] )
delete disasmWindow [ 0 ] ;
disasmWindow [ 0 ] = 0 ;
DialogManager : : RemoveDlg ( geDebuggerWindow ) ;
if ( geDebuggerWindow )
delete geDebuggerWindow ;
geDebuggerWindow = 0 ;
DialogManager : : RemoveDlg ( memoryWindow [ 0 ] ) ;
if ( memoryWindow [ 0 ] )
delete memoryWindow [ 0 ] ;
memoryWindow [ 0 ] = 0 ;
}
2013-07-29 15:34:30 -04:00
void BrowseAndBoot ( std : : string defaultPath , bool browseDirectory ) {
2014-01-19 18:44:41 -08:00
static std : : wstring filter = L " All supported file types (*.iso *.cso *.pbp *.elf *.prx *.zip)|*.pbp;*.elf;*.iso;*.cso;*.prx;*.zip|PSP ROMs (*.iso *.cso *.pbp *.elf *.prx)|*.pbp;*.elf;*.iso;*.cso;*.prx|Homebrew/Demos installers (*.zip)|*.zip|All files (*.*)|*.*|| " ;
for ( int i = 0 ; i < ( int ) filter . length ( ) ; i + + ) {
2012-11-01 16:19:01 +01:00
if ( filter [ i ] = = ' | ' )
filter [ i ] = ' \0 ' ;
}
2014-01-19 18:44:41 -08:00
browsePauseAfter = false ;
2014-06-22 09:38:46 +02:00
if ( GetUIState ( ) = = UISTATE_INGAME ) {
2014-01-19 18:44:41 -08:00
browsePauseAfter = Core_IsStepping ( ) ;
if ( ! browsePauseAfter )
2013-07-17 02:33:26 -03:00
Core_EnableStepping ( true ) ;
}
2014-01-19 18:44:41 -08:00
W32Util : : MakeTopMost ( GetHWND ( ) , false ) ;
2013-07-29 15:34:30 -04:00
if ( browseDirectory ) {
2014-01-19 18:44:41 -08:00
browseDialog = new W32Util : : AsyncBrowseDialog ( GetHWND ( ) , WM_USER_BROWSE_BOOT_DONE , L " Choose directory " ) ;
} else {
browseDialog = new W32Util : : AsyncBrowseDialog ( W32Util : : AsyncBrowseDialog : : OPEN , GetHWND ( ) , WM_USER_BROWSE_BOOT_DONE , L " LoadFile " , ConvertUTF8ToWString ( defaultPath ) , filter , L " *.pbp;*.elf;*.iso;*.cso; " ) ;
2013-07-23 17:24:33 +02:00
}
2014-01-19 18:44:41 -08:00
}
void BrowseAndBootDone ( ) {
std : : string filename ;
if ( ! browseDialog - > GetResult ( filename ) ) {
if ( ! browsePauseAfter ) {
Core_EnableStepping ( false ) ;
}
} else {
2014-06-22 09:38:46 +02:00
if ( GetUIState ( ) = = UISTATE_INGAME | | GetUIState ( ) = = UISTATE_PAUSEMENU ) {
2013-07-17 02:33:26 -03:00
Core_EnableStepping ( false ) ;
}
2014-01-19 18:44:41 -08:00
// TODO: What is this for / what does it fix?
if ( browseDialog - > GetType ( ) ! = W32Util : : AsyncBrowseDialog : : DIR ) {
// Decode the filename with fullpath.
char drive [ MAX_PATH ] ;
char dir [ MAX_PATH ] ;
char fname [ MAX_PATH ] ;
char ext [ MAX_PATH ] ;
_splitpath ( filename . c_str ( ) , drive , dir , fname , ext ) ;
filename = std : : string ( drive ) + std : : string ( dir ) + std : : string ( fname ) + std : : string ( ext ) ;
}
filename = ReplaceAll ( filename , " \\ " , " / " ) ;
NativeMessageReceived ( " boot " , filename . c_str ( ) ) ;
2013-07-17 02:33:26 -03:00
}
2014-01-19 18:44:41 -08:00
W32Util : : MakeTopMost ( GetHWND ( ) , g_Config . bTopMost ) ;
delete browseDialog ;
browseDialog = 0 ;
2012-11-01 16:19:01 +01:00
}
2013-11-27 21:57:17 +08:00
void UmdSwitchAction ( ) {
std : : string fn ;
std : : string filter = " PSP ROMs (*.iso *.cso *.pbp *.elf)|*.pbp;*.elf;*.iso;*.cso;*.prx|All files (*.*)|*.*|| " ;
for ( int i = 0 ; i < ( int ) filter . length ( ) ; i + + ) {
if ( filter [ i ] = = ' | ' )
filter [ i ] = ' \0 ' ;
}
if ( W32Util : : BrowseForFileName ( true , GetHWND ( ) , L " Switch Umd " , 0 , ConvertUTF8ToWString ( filter ) . c_str ( ) , L " *.pbp;*.elf;*.iso;*.cso; " , fn ) ) {
fn = ReplaceAll ( fn , " \\ " , " / " ) ;
__UmdReplace ( fn ) ;
}
}
2014-06-29 22:13:53 +02:00
LRESULT CALLBACK DisplayProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) {
2013-09-23 23:56:32 -04:00
// Only apply a factor > 1 in windowed mode.
2015-05-15 18:04:05 +02:00
int factor = ! IsZoomed ( GetHWND ( ) ) & & ! g_Config . bFullScreen & & IsWindowSmall ( ) ? 2 : 1 ;
2014-06-23 20:04:31 +02:00
static bool firstErase = true ;
2013-09-23 23:56:32 -04:00
2013-07-29 15:34:30 -04:00
switch ( message ) {
2014-06-29 22:13:53 +02:00
case WM_ACTIVATE :
if ( wParam = = WA_ACTIVE | | wParam = = WA_CLICKACTIVE ) {
g_activeWindow = WINDOW_MAINWINDOW ;
2014-06-29 13:11:06 +02:00
}
2012-11-01 16:19:01 +01:00
break ;
2013-03-29 19:32:20 +01:00
2014-06-29 22:13:53 +02:00
case WM_SETFOCUS :
break ;
2014-06-23 20:23:11 +02:00
2012-11-01 16:19:01 +01:00
case WM_ERASEBKGND :
2014-06-23 20:04:31 +02:00
if ( firstErase ) {
firstErase = false ;
// Paint black on first erase while OpenGL stuff is loading
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
// Then never erase, let the OpenGL drawing take care of everything.
return 1 ;
2013-03-29 19:32:20 +01:00
2013-06-01 23:34:50 +02:00
// Poor man's touch - mouse input. We send the data both as an input_state pointer,
// and as asynchronous touch events for minimal latency.
2012-11-01 16:19:01 +01:00
case WM_LBUTTONDOWN :
2014-02-24 13:28:20 +01:00
if ( ! touchHandler . hasTouch ( ) | |
( GetMessageExtraInfo ( ) & MOUSEEVENTF_MASK_PLUS_PENTOUCH ) ! = MOUSEEVENTF_FROMTOUCH_NOPEN )
2014-01-23 18:05:42 +01:00
{
2013-07-09 22:51:02 +02:00
// Hack: Take the opportunity to show the cursor.
mouseButtonDown = true ;
{
lock_guard guard ( input_state . lock ) ;
input_state . mouse_valid = true ;
input_state . pointer_down [ 0 ] = true ;
2013-03-31 19:15:59 -07:00
2013-09-23 23:56:32 -04:00
input_state . pointer_x [ 0 ] = GET_X_LPARAM ( lParam ) * factor ;
input_state . pointer_y [ 0 ] = GET_Y_LPARAM ( lParam ) * factor ;
2013-07-09 22:51:02 +02:00
}
2013-06-01 23:34:50 +02:00
TouchInput touch ;
touch . id = 0 ;
touch . flags = TOUCH_DOWN ;
2013-07-09 14:46:15 +02:00
touch . x = input_state . pointer_x [ 0 ] ;
touch . y = input_state . pointer_y [ 0 ] ;
2013-06-01 23:34:50 +02:00
NativeTouch ( touch ) ;
2013-07-09 22:51:02 +02:00
SetCapture ( hWnd ) ;
2014-02-24 13:28:20 +01:00
2013-03-29 18:50:08 +01:00
}
2013-07-29 15:34:30 -04:00
break ;
2013-03-29 18:50:08 +01:00
case WM_MOUSEMOVE :
2014-02-24 13:28:20 +01:00
if ( ! touchHandler . hasTouch ( ) | |
( GetMessageExtraInfo ( ) & MOUSEEVENTF_MASK_PLUS_PENTOUCH ) ! = MOUSEEVENTF_FROMTOUCH_NOPEN )
2013-03-29 18:50:08 +01:00
{
2013-06-12 02:14:53 +08:00
// Hack: Take the opportunity to show the cursor.
mouseButtonDown = ( wParam & MK_LBUTTON ) ! = 0 ;
int cursorX = GET_X_LPARAM ( lParam ) ;
int cursorY = GET_Y_LPARAM ( lParam ) ;
if ( abs ( cursorX - prevCursorX ) > 1 | | abs ( cursorY - prevCursorY ) > 1 ) {
hideCursor = false ;
SetTimer ( hwndMain , TIMER_CURSORMOVEUPDATE , CURSORUPDATE_MOVE_TIMESPAN_MS , 0 ) ;
}
prevCursorX = cursorX ;
prevCursorY = cursorY ;
2013-07-09 22:51:02 +02:00
{
lock_guard guard ( input_state . lock ) ;
2013-09-23 23:56:32 -04:00
input_state . pointer_x [ 0 ] = GET_X_LPARAM ( lParam ) * factor ;
input_state . pointer_y [ 0 ] = GET_Y_LPARAM ( lParam ) * factor ;
2013-07-09 22:51:02 +02:00
}
2013-06-01 23:34:50 +02:00
if ( wParam & MK_LBUTTON ) {
TouchInput touch ;
touch . id = 0 ;
touch . flags = TOUCH_MOVE ;
2013-07-09 14:46:15 +02:00
touch . x = input_state . pointer_x [ 0 ] ;
touch . y = input_state . pointer_y [ 0 ] ;
2013-06-01 23:34:50 +02:00
NativeTouch ( touch ) ;
2013-03-31 19:15:59 -07:00
}
2013-03-29 18:50:08 +01:00
}
2012-11-01 16:19:01 +01:00
break ;
2013-03-29 18:50:08 +01:00
case WM_LBUTTONUP :
2014-02-24 13:28:20 +01:00
if ( ! touchHandler . hasTouch ( ) | |
( GetMessageExtraInfo ( ) & MOUSEEVENTF_MASK_PLUS_PENTOUCH ) ! = MOUSEEVENTF_FROMTOUCH_NOPEN )
2013-03-29 18:50:08 +01:00
{
2013-07-09 22:51:02 +02:00
// Hack: Take the opportunity to hide the cursor.
mouseButtonDown = false ;
{
lock_guard guard ( input_state . lock ) ;
input_state . pointer_down [ 0 ] = false ;
2013-09-23 23:56:32 -04:00
input_state . pointer_x [ 0 ] = GET_X_LPARAM ( lParam ) * factor ;
input_state . pointer_y [ 0 ] = GET_Y_LPARAM ( lParam ) * factor ;
2013-07-09 22:51:02 +02:00
}
2013-06-01 23:34:50 +02:00
TouchInput touch ;
touch . id = 0 ;
touch . flags = TOUCH_UP ;
2013-07-09 14:46:15 +02:00
touch . x = input_state . pointer_x [ 0 ] ;
touch . y = input_state . pointer_y [ 0 ] ;
2013-06-01 23:34:50 +02:00
NativeTouch ( touch ) ;
2013-07-09 22:51:02 +02:00
ReleaseCapture ( ) ;
2013-03-29 18:50:08 +01:00
}
2013-07-29 15:34:30 -04:00
break ;
2013-03-29 18:50:08 +01:00
2013-04-16 21:12:55 +02:00
case WM_TOUCH :
{
2014-01-19 22:54:49 +01:00
touchHandler . handleTouchEvent ( hWnd , message , wParam , lParam ) ;
2014-02-24 12:11:40 +01:00
return 0 ;
2013-04-16 21:12:55 +02:00
}
2014-06-29 22:13:53 +02:00
default :
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
return 0 ;
}
LRESULT CALLBACK WndProc ( HWND hWnd , UINT message , WPARAM wParam , LPARAM lParam ) {
int wmId , wmEvent ;
std : : string fn ;
static bool noFocusPause = false ; // TOGGLE_PAUSE state to override pause on lost focus
switch ( message ) {
case WM_CREATE :
break ;
case WM_GETMINMAXINFO :
{
MINMAXINFO * minmax = reinterpret_cast < MINMAXINFO * > ( lParam ) ;
RECT rc = { 0 } ;
2015-05-15 18:04:05 +02:00
bool portrait = g_Config . IsPortrait ( ) ;
rc . right = portrait ? 272 : 480 ;
rc . bottom = portrait ? 480 : 272 ;
2014-06-29 22:13:53 +02:00
AdjustWindowRect ( & rc , WS_OVERLAPPEDWINDOW , TRUE ) ;
minmax - > ptMinTrackSize . x = rc . right - rc . left ;
minmax - > ptMinTrackSize . y = rc . bottom - rc . top ;
}
return 0 ;
2013-09-28 14:34:08 +02:00
case WM_ACTIVATE :
2013-10-11 14:53:25 +03:00
{
bool pause = true ;
if ( wParam = = WA_ACTIVE | | wParam = = WA_CLICKACTIVE ) {
2015-02-28 16:01:41 -08:00
WindowsRawInput : : GainFocus ( ) ;
2015-02-28 14:02:03 -08:00
InputDevice : : GainFocus ( ) ;
2013-10-11 14:53:25 +03:00
g_activeWindow = WINDOW_MAINWINDOW ;
pause = false ;
}
2014-06-22 09:38:46 +02:00
if ( ! noFocusPause & & g_Config . bPauseOnLostFocus & & GetUIState ( ) = = UISTATE_INGAME ) {
2013-10-11 14:53:25 +03:00
if ( pause ! = Core_IsStepping ( ) ) { // != is xor for bools
if ( disasmWindow [ 0 ] )
SendMessage ( disasmWindow [ 0 ] - > GetDlgHandle ( ) , WM_COMMAND , IDC_STOPGO , 0 ) ;
else
Core_EnableStepping ( pause ) ;
}
}
2013-10-31 00:34:09 +01:00
2015-05-21 10:49:47 +02:00
if ( wParam = = WA_ACTIVE ) {
NativeMessageReceived ( " got_focus " , " " ) ;
}
2013-10-31 00:34:09 +01:00
if ( wParam = = WA_INACTIVE ) {
2015-05-21 10:49:47 +02:00
NativeMessageReceived ( " lost_focus " , " " ) ;
2014-01-19 11:59:11 -08:00
WindowsRawInput : : LoseFocus ( ) ;
2015-02-28 14:02:03 -08:00
InputDevice : : LoseFocus ( ) ;
2013-10-31 00:34:09 +01:00
}
2013-09-28 14:34:08 +02:00
}
break ;
2012-11-01 16:19:01 +01:00
2014-06-29 22:13:53 +02:00
case WM_ERASEBKGND :
// This window is always covered by DisplayWindow. No reason to erase.
return 1 ;
2012-11-01 16:19:01 +01:00
case WM_MOVE :
2013-03-30 17:49:02 +01:00
SavePosition ( ) ;
2013-01-27 00:15:39 +01:00
break ;
2014-06-29 22:13:53 +02:00
case WM_SIZE :
if ( ! g_inModeSwitch ) {
switch ( wParam ) {
case SIZE_MAXIMIZED :
case SIZE_RESTORED :
Core_NotifyWindowHidden ( false ) ;
2014-06-29 18:06:47 -04:00
if ( ! g_Config . bPauseWhenMinimized ) {
NativeMessageReceived ( " window minimized " , " false " ) ;
}
2014-06-29 22:13:53 +02:00
SavePosition ( ) ;
ResizeDisplay ( ) ;
2014-07-29 18:18:57 -04:00
g_WindowState = wParam ;
2014-06-29 22:13:53 +02:00
break ;
case SIZE_MINIMIZED :
2014-06-30 13:04:44 -04:00
Core_NotifyWindowHidden ( true ) ;
2014-06-29 18:06:47 -04:00
if ( ! g_Config . bPauseWhenMinimized ) {
NativeMessageReceived ( " window minimized " , " true " ) ;
}
2014-06-29 22:13:53 +02:00
break ;
default :
break ;
}
}
2015-01-17 19:49:58 -08:00
break ;
2014-06-29 22:13:53 +02:00
case WM_TIMER :
2013-05-04 23:21:06 +02:00
// Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode.
2013-07-29 04:46:40 -04:00
switch ( wParam ) {
2013-06-12 02:14:53 +08:00
case TIMER_CURSORUPDATE :
CorrectCursor ( ) ;
return 0 ;
2013-07-29 15:34:30 -04:00
2013-06-12 02:14:53 +08:00
case TIMER_CURSORMOVEUPDATE :
hideCursor = true ;
KillTimer ( hWnd , TIMER_CURSORMOVEUPDATE ) ;
return 0 ;
}
break ;
2013-05-04 23:21:06 +02:00
2013-07-08 12:35:08 +02:00
// For some reason, need to catch this here rather than in DisplayProc.
case WM_MOUSEWHEEL :
{
int wheelDelta = ( short ) ( wParam > > 16 ) ;
KeyInput key ;
key . deviceId = DEVICE_ID_MOUSE ;
if ( wheelDelta < 0 ) {
2013-08-05 03:31:40 +10:00
key . keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN ;
2013-07-08 12:35:08 +02:00
wheelDelta = - wheelDelta ;
} else {
2013-08-05 03:31:40 +10:00
key . keyCode = NKCODE_EXT_MOUSEWHEEL_UP ;
2013-07-08 12:35:08 +02:00
}
// There's no separate keyup event for mousewheel events, let's pass them both together.
// This also means it really won't work great for key mapping :( Need to build a 1 frame delay or something.
key . flags = KEY_DOWN | KEY_UP | KEY_HASWHEELDELTA | ( wheelDelta < < 16 ) ;
NativeKey ( key ) ;
}
2013-07-29 15:34:30 -04:00
break ;
2013-07-08 12:35:08 +02:00
2012-11-01 16:19:01 +01:00
case WM_COMMAND :
2013-06-03 20:30:12 +08:00
{
2013-07-29 04:46:40 -04:00
if ( ! EmuThread_Ready ( ) )
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
2015-07-01 23:50:16 +02:00
I18NCategory * gr = GetI18NCategory ( " Graphics " ) ;
2013-07-29 04:46:40 -04:00
wmId = LOWORD ( wParam ) ;
wmEvent = HIWORD ( wParam ) ;
// Parse the menu selections:
switch ( wmId ) {
case ID_FILE_LOAD :
BrowseAndBoot ( " " ) ;
break ;
2013-03-28 20:26:24 +01:00
2013-07-29 04:46:40 -04:00
case ID_FILE_LOAD_DIR :
BrowseAndBoot ( " " , true ) ;
break ;
2013-07-23 17:24:33 +02:00
2013-07-29 04:46:40 -04:00
case ID_FILE_LOAD_MEMSTICK :
2013-10-15 02:03:39 -04:00
BrowseAndBoot ( GetSysDirectory ( DIRECTORY_GAME ) ) ;
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_FILE_MEMSTICK :
2014-10-19 23:20:51 +02:00
ShellExecute ( NULL , L " open " , ConvertUTF8ToWString ( g_Config . memStickDirectory ) . c_str ( ) , 0 , 0 , SW_SHOW ) ;
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_TOGGLE_PAUSE :
2014-06-22 09:38:46 +02:00
if ( GetUIState ( ) = = UISTATE_PAUSEMENU ) {
2013-08-20 17:07:01 +02:00
// Causes hang
//NativeMessageReceived("run", "");
2013-07-29 04:46:40 -04:00
if ( disasmWindow [ 0 ] )
2013-08-17 10:57:29 +02:00
SendMessage ( disasmWindow [ 0 ] - > GetDlgHandle ( ) , WM_COMMAND , IDC_STOPGO , 0 ) ;
2013-07-29 04:46:40 -04:00
}
else if ( Core_IsStepping ( ) ) { // It is paused, then continue to run.
if ( disasmWindow [ 0 ] )
2013-08-17 10:57:29 +02:00
SendMessage ( disasmWindow [ 0 ] - > GetDlgHandle ( ) , WM_COMMAND , IDC_STOPGO , 0 ) ;
2013-07-29 04:46:40 -04:00
else
Core_EnableStepping ( false ) ;
} else {
if ( disasmWindow [ 0 ] )
2013-08-17 10:57:29 +02:00
SendMessage ( disasmWindow [ 0 ] - > GetDlgHandle ( ) , WM_COMMAND , IDC_STOPGO , 0 ) ;
2013-07-29 04:46:40 -04:00
else
Core_EnableStepping ( true ) ;
}
2013-10-11 14:53:25 +03:00
noFocusPause = ! noFocusPause ; // If we pause, override pause on lost focus
2013-07-29 04:46:40 -04:00
break ;
2013-03-28 20:17:45 +01:00
2013-07-29 04:46:40 -04:00
case ID_EMULATION_STOP :
2013-12-06 01:30:24 -05:00
if ( Core_IsStepping ( ) )
Core_EnableStepping ( false ) ;
2013-10-12 02:19:35 -07:00
Core_Stop ( ) ;
2013-07-29 04:46:40 -04:00
NativeMessageReceived ( " stop " , " " ) ;
2013-10-12 02:19:35 -07:00
Core_WaitInactive ( ) ;
2013-07-29 04:46:40 -04:00
Update ( ) ;
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_EMULATION_RESET :
NativeMessageReceived ( " reset " , " " ) ;
2013-10-12 02:08:18 -07:00
Core_EnableStepping ( false ) ;
2013-07-29 04:46:40 -04:00
break ;
2014-06-23 20:04:31 +02:00
2013-11-27 21:57:17 +08:00
case ID_EMULATION_SWITCH_UMD :
UmdSwitchAction ( ) ;
break ;
2013-09-26 22:44:29 -04:00
2013-08-24 05:43:14 -04:00
case ID_EMULATION_CHEATS :
2013-09-02 18:33:00 +05:00
g_Config . bEnableCheats = ! g_Config . bEnableCheats ;
2015-07-01 23:50:16 +02:00
osm . ShowOnOff ( gr - > T ( " Cheats " ) , g_Config . bEnableCheats ) ;
2013-08-23 22:28:21 -05:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_FILE_LOADSTATEFILE :
2013-08-26 21:32:05 +02:00
if ( W32Util : : BrowseForFileName ( true , hWnd , L " Load state " , 0 , L " Save States (*.ppst) \0 *.ppst \0 All files \0 *.* \0 \0 " , L " ppst " , fn ) ) {
2013-07-29 04:46:40 -04:00
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
SaveState : : Load ( fn , SaveStateActionFinished ) ;
}
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_FILE_SAVESTATEFILE :
2013-08-26 21:32:05 +02:00
if ( W32Util : : BrowseForFileName ( false , hWnd , L " Save state " , 0 , L " Save States (*.ppst) \0 *.ppst \0 All files \0 *.* \0 \0 " , L " ppst " , fn ) ) {
2013-07-29 04:46:40 -04:00
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
SaveState : : Save ( fn , SaveStateActionFinished ) ;
}
break ;
case ID_FILE_SAVESTATE_NEXT_SLOT :
2012-11-01 16:19:01 +01:00
{
2014-01-07 15:56:04 +01:00
SaveState : : NextSlot ( ) ;
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
}
2014-06-06 11:51:59 +03:00
case ID_FILE_SAVESTATE_NEXT_SLOT_HC :
{
2015-01-19 09:01:55 -08:00
if ( KeyMap : : g_controllerMap [ VIRTKEY_NEXT_SLOT ] . empty ( ) )
2014-06-06 11:51:59 +03:00
{
SaveState : : NextSlot ( ) ;
}
break ;
}
2013-09-11 00:19:34 +02:00
case ID_FILE_SAVESTATE_SLOT_1 : g_Config . iCurrentStateSlot = 0 ; break ;
case ID_FILE_SAVESTATE_SLOT_2 : g_Config . iCurrentStateSlot = 1 ; break ;
case ID_FILE_SAVESTATE_SLOT_3 : g_Config . iCurrentStateSlot = 2 ; break ;
case ID_FILE_SAVESTATE_SLOT_4 : g_Config . iCurrentStateSlot = 3 ; break ;
case ID_FILE_SAVESTATE_SLOT_5 : g_Config . iCurrentStateSlot = 4 ; break ;
2013-09-07 11:29:44 -04:00
2013-07-29 04:46:40 -04:00
case ID_FILE_QUICKLOADSTATE :
2014-06-06 11:51:59 +03:00
{
2013-07-09 17:25:29 -03:00
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
2013-09-07 11:29:44 -04:00
SaveState : : LoadSlot ( g_Config . iCurrentStateSlot , SaveStateActionFinished ) ;
2013-07-29 04:46:40 -04:00
break ;
2014-06-06 11:51:59 +03:00
}
2012-11-01 16:19:01 +01:00
2014-06-06 11:51:59 +03:00
case ID_FILE_QUICKLOADSTATE_HC :
{
2015-01-19 09:01:55 -08:00
if ( KeyMap : : g_controllerMap [ VIRTKEY_LOAD_STATE ] . empty ( ) )
2014-06-06 11:51:59 +03:00
{
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
SaveState : : LoadSlot ( g_Config . iCurrentStateSlot , SaveStateActionFinished ) ;
}
break ;
}
2013-07-29 04:46:40 -04:00
case ID_FILE_QUICKSAVESTATE :
2014-06-06 11:51:59 +03:00
{
2013-07-29 04:46:40 -04:00
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
2013-09-07 11:29:44 -04:00
SaveState : : SaveSlot ( g_Config . iCurrentStateSlot , SaveStateActionFinished ) ;
2013-07-29 04:46:40 -04:00
break ;
2014-06-06 11:51:59 +03:00
}
case ID_FILE_QUICKSAVESTATE_HC :
{
2015-01-19 09:01:55 -08:00
if ( KeyMap : : g_controllerMap [ VIRTKEY_SAVE_STATE ] . empty ( ) )
2014-06-06 11:51:59 +03:00
{
SetCursor ( LoadCursor ( 0 , IDC_WAIT ) ) ;
SaveState : : SaveSlot ( g_Config . iCurrentStateSlot , SaveStateActionFinished ) ;
break ;
}
}
2013-01-02 21:00:10 +01:00
2013-11-02 20:24:19 -04:00
case ID_OPTIONS_LANGUAGE :
NativeMessageReceived ( " language screen " , " " ) ;
break ;
2014-01-07 16:08:11 -05:00
case ID_OPTIONS_IGNOREWINKEY :
g_Config . bIgnoreWindowsKey = ! g_Config . bIgnoreWindowsKey ;
break ;
2013-09-19 23:27:25 -04:00
case ID_OPTIONS_SCREENAUTO : SetInternalResolution ( RESOLUTION_AUTO ) ; break ;
case ID_OPTIONS_SCREEN1X : SetInternalResolution ( RESOLUTION_NATIVE ) ; break ;
case ID_OPTIONS_SCREEN2X : SetInternalResolution ( RESOLUTION_2X ) ; break ;
case ID_OPTIONS_SCREEN3X : SetInternalResolution ( RESOLUTION_3X ) ; break ;
case ID_OPTIONS_SCREEN4X : SetInternalResolution ( RESOLUTION_4X ) ; break ;
case ID_OPTIONS_SCREEN5X : SetInternalResolution ( RESOLUTION_5X ) ; break ;
case ID_OPTIONS_SCREEN6X : SetInternalResolution ( RESOLUTION_6X ) ; break ;
case ID_OPTIONS_SCREEN7X : SetInternalResolution ( RESOLUTION_7X ) ; break ;
case ID_OPTIONS_SCREEN8X : SetInternalResolution ( RESOLUTION_8X ) ; break ;
case ID_OPTIONS_SCREEN9X : SetInternalResolution ( RESOLUTION_9X ) ; break ;
case ID_OPTIONS_SCREEN10X : SetInternalResolution ( RESOLUTION_MAX ) ; break ;
2013-07-29 04:46:40 -04:00
2013-09-11 00:19:34 +02:00
case ID_OPTIONS_WINDOW1X : SetWindowSize ( 1 ) ; break ;
case ID_OPTIONS_WINDOW2X : SetWindowSize ( 2 ) ; break ;
case ID_OPTIONS_WINDOW3X : SetWindowSize ( 3 ) ; break ;
case ID_OPTIONS_WINDOW4X : SetWindowSize ( 4 ) ; break ;
2013-09-11 10:20:14 +08:00
case ID_OPTIONS_RESOLUTIONDUMMY :
{
2013-09-19 14:32:56 -04:00
SetInternalResolution ( ) ;
2013-09-11 10:20:14 +08:00
break ;
}
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_VSYNC :
g_Config . bVSync = ! g_Config . bVSync ;
2013-07-26 20:25:11 +08:00
break ;
2013-10-12 02:05:55 +02:00
2014-01-25 21:41:39 +05:00
case ID_OPTIONS_FRAMESKIP_AUTO :
g_Config . bAutoFrameSkip = ! g_Config . bAutoFrameSkip ;
2015-02-09 23:10:57 +01:00
if ( g_Config . bAutoFrameSkip & & g_Config . iRenderingMode = = FB_NON_BUFFERED_MODE )
g_Config . iRenderingMode = FB_BUFFERED_MODE ;
2014-01-25 21:41:39 +05:00
break ;
2013-10-11 11:49:45 +05:00
case ID_TEXTURESCALING_AUTO : setTexScalingMultiplier ( TEXSCALING_AUTO ) ; break ;
2013-09-11 00:19:34 +02:00
case ID_TEXTURESCALING_OFF : setTexScalingMultiplier ( TEXSCALING_OFF ) ; break ;
case ID_TEXTURESCALING_2X : setTexScalingMultiplier ( TEXSCALING_2X ) ; break ;
case ID_TEXTURESCALING_3X : setTexScalingMultiplier ( TEXSCALING_3X ) ; break ;
case ID_TEXTURESCALING_4X : setTexScalingMultiplier ( TEXSCALING_4X ) ; break ;
case ID_TEXTURESCALING_5X : setTexScalingMultiplier ( TEXSCALING_MAX ) ; break ;
2013-07-21 23:17:42 +08:00
2013-09-11 00:19:34 +02:00
case ID_TEXTURESCALING_XBRZ : setTexScalingType ( TextureScaler : : XBRZ ) ; break ;
case ID_TEXTURESCALING_HYBRID : setTexScalingType ( TextureScaler : : HYBRID ) ; break ;
case ID_TEXTURESCALING_BICUBIC : setTexScalingType ( TextureScaler : : BICUBIC ) ; break ;
case ID_TEXTURESCALING_HYBRID_BICUBIC : setTexScalingType ( TextureScaler : : HYBRID_BICUBIC ) ; break ;
2012-11-20 11:35:48 +01:00
2013-07-29 04:46:40 -04:00
case ID_TEXTURESCALING_DEPOSTERIZE :
g_Config . bTexDeposterize = ! g_Config . bTexDeposterize ;
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu clear cache " , " " ) ;
2013-07-29 04:46:40 -04:00
break ;
2013-07-23 17:05:58 -04:00
2014-09-14 07:30:49 -04:00
case ID_OPTIONS_DIRECTX :
g_Config . iTempGPUBackend = GPU_BACKEND_DIRECT3D9 ;
g_Config . bRestartRequired = true ;
PostMessage ( MainWindow : : GetHWND ( ) , WM_CLOSE , 0 , 0 ) ;
break ;
case ID_OPTIONS_OPENGL :
g_Config . iTempGPUBackend = GPU_BACKEND_OPENGL ;
g_Config . bRestartRequired = true ;
PostMessage ( MainWindow : : GetHWND ( ) , WM_CLOSE , 0 , 0 ) ;
break ;
2013-09-11 00:19:34 +02:00
case ID_OPTIONS_NONBUFFEREDRENDERING : setRenderingMode ( FB_NON_BUFFERED_MODE ) ; break ;
case ID_OPTIONS_BUFFEREDRENDERING : setRenderingMode ( FB_BUFFERED_MODE ) ; break ;
case ID_OPTIONS_READFBOTOMEMORYCPU : setRenderingMode ( FB_READFBOMEMORY_CPU ) ; break ;
case ID_OPTIONS_READFBOTOMEMORYGPU : setRenderingMode ( FB_READFBOMEMORY_GPU ) ; break ;
2013-07-29 04:46:40 -04:00
// Dummy option to let the buffered rendering hotkey cycle through all the options.
case ID_OPTIONS_BUFFEREDRENDERINGDUMMY :
2013-09-19 21:18:26 -04:00
setRenderingMode ( ) ;
2013-07-23 17:05:58 -04:00
break ;
2013-07-29 04:46:40 -04:00
2013-09-07 11:29:44 -04:00
case ID_DEBUG_SHOWDEBUGSTATISTICS :
2013-07-29 04:46:40 -04:00
g_Config . bShowDebugStats = ! g_Config . bShowDebugStats ;
2013-11-02 13:33:27 -07:00
NativeMessageReceived ( " clear jit " , " " ) ;
2013-07-23 17:05:58 -04:00
break ;
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_HARDWARETRANSFORM :
g_Config . bHardwareTransform = ! g_Config . bHardwareTransform ;
2015-07-01 23:50:16 +02:00
osm . ShowOnOff ( gr - > T ( " Hardware Transform " ) , g_Config . bHardwareTransform ) ;
2013-07-29 04:46:40 -04:00
break ;
2013-07-23 17:05:58 -04:00
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_STRETCHDISPLAY :
g_Config . bStretchToDisplay = ! g_Config . bStretchToDisplay ;
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu resized " , " " ) ;
2013-07-29 04:46:40 -04:00
break ;
2013-07-23 17:05:58 -04:00
2013-09-11 00:19:34 +02:00
case ID_OPTIONS_FRAMESKIP_0 : setFrameSkipping ( FRAMESKIP_OFF ) ; break ;
case ID_OPTIONS_FRAMESKIP_1 : setFrameSkipping ( FRAMESKIP_1 ) ; break ;
case ID_OPTIONS_FRAMESKIP_2 : setFrameSkipping ( FRAMESKIP_2 ) ; break ;
case ID_OPTIONS_FRAMESKIP_3 : setFrameSkipping ( FRAMESKIP_3 ) ; break ;
case ID_OPTIONS_FRAMESKIP_4 : setFrameSkipping ( FRAMESKIP_4 ) ; break ;
case ID_OPTIONS_FRAMESKIP_5 : setFrameSkipping ( FRAMESKIP_5 ) ; break ;
case ID_OPTIONS_FRAMESKIP_6 : setFrameSkipping ( FRAMESKIP_6 ) ; break ;
case ID_OPTIONS_FRAMESKIP_7 : setFrameSkipping ( FRAMESKIP_7 ) ; break ;
case ID_OPTIONS_FRAMESKIP_8 : setFrameSkipping ( FRAMESKIP_MAX ) ; break ;
2013-07-26 20:25:11 +08:00
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_FRAMESKIPDUMMY :
2013-09-19 21:18:26 -04:00
setFrameSkipping ( ) ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
case ID_FILE_EXIT :
2014-04-11 14:18:27 -04:00
PostMessage ( hwndMain , WM_CLOSE , 0 , 0 ) ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
2013-09-07 11:29:44 -04:00
case ID_DEBUG_RUNONLOAD :
2013-07-29 04:46:40 -04:00
g_Config . bAutoRun = ! g_Config . bAutoRun ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_DUMPNEXTFRAME :
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu dump next frame " , " " ) ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_LOADMAPFILE :
2014-01-25 21:12:16 -08:00
if ( W32Util : : BrowseForFileName ( true , hWnd , L " Load .ppmap " , 0 , L " Maps \0 *.ppmap \0 All files \0 *.* \0 \0 " , L " ppmap " , fn ) ) {
2013-07-29 04:46:40 -04:00
symbolMap . LoadSymbolMap ( fn . c_str ( ) ) ;
if ( disasmWindow [ 0 ] )
disasmWindow [ 0 ] - > NotifyMapLoaded ( ) ;
if ( memoryWindow [ 0 ] )
memoryWindow [ 0 ] - > NotifyMapLoaded ( ) ;
}
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_SAVEMAPFILE :
2014-01-25 21:12:16 -08:00
if ( W32Util : : BrowseForFileName ( false , hWnd , L " Save .ppmap " , 0 , L " Maps \0 *.ppmap \0 All files \0 *.* \0 \0 " , L " ppmap " , fn ) )
2013-07-29 04:46:40 -04:00
symbolMap . SaveSymbolMap ( fn . c_str ( ) ) ;
2013-07-26 20:25:11 +08:00
break ;
2014-06-30 00:02:22 +02:00
case ID_DEBUG_LOADSYMFILE :
if ( W32Util : : BrowseForFileName ( true , hWnd , L " Load .sym " , 0 , L " Symbols \0 *.sym \0 All files \0 *.* \0 \0 " , L " sym " , fn ) ) {
symbolMap . LoadNocashSym ( fn . c_str ( ) ) ;
if ( disasmWindow [ 0 ] )
disasmWindow [ 0 ] - > NotifyMapLoaded ( ) ;
if ( memoryWindow [ 0 ] )
memoryWindow [ 0 ] - > NotifyMapLoaded ( ) ;
}
break ;
case ID_DEBUG_SAVESYMFILE :
if ( W32Util : : BrowseForFileName ( false , hWnd , L " Save .sym " , 0 , L " Symbols \0 *.sym \0 All files \0 *.* \0 \0 " , L " sym " , fn ) )
symbolMap . SaveNocashSym ( fn . c_str ( ) ) ;
break ;
2013-10-18 15:07:04 +02:00
2013-07-29 04:46:40 -04:00
case ID_DEBUG_RESETSYMBOLTABLE :
2013-10-18 15:07:04 +02:00
symbolMap . Clear ( ) ;
2013-07-29 04:46:40 -04:00
for ( int i = 0 ; i < numCPUs ; i + + )
if ( disasmWindow [ i ] )
disasmWindow [ i ] - > NotifyMapLoaded ( ) ;
for ( int i = 0 ; i < numCPUs ; i + + )
if ( memoryWindow [ i ] )
memoryWindow [ i ] - > NotifyMapLoaded ( ) ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_DISASSEMBLY :
2014-02-14 21:17:36 -08:00
if ( disasmWindow [ 0 ] )
disasmWindow [ 0 ] - > Show ( true ) ;
2013-07-26 20:25:11 +08:00
break ;
2013-07-29 04:46:40 -04:00
2013-09-22 10:27:09 -07:00
case ID_DEBUG_GEDEBUGGER :
2014-02-14 21:17:36 -08:00
if ( geDebuggerWindow )
geDebuggerWindow - > Show ( true ) ;
2013-09-22 10:27:09 -07:00
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_MEMORYVIEW :
2014-02-14 21:17:36 -08:00
if ( memoryWindow [ 0 ] )
memoryWindow [ 0 ] - > Show ( true ) ;
2013-07-26 20:25:11 +08:00
break ;
2014-01-01 16:45:37 -08:00
case ID_DEBUG_EXTRACTFILE :
{
std : : string filename ;
if ( ! InputBox_GetString ( hInst , hwndMain , L " Disc filename " , filename , filename ) ) {
break ;
}
const char * lastSlash = strrchr ( filename . c_str ( ) , ' / ' ) ;
if ( lastSlash ) {
fn = lastSlash + 1 ;
} else {
fn = " " ;
}
PSPFileInfo info = pspFileSystem . GetFileInfo ( filename ) ;
if ( ! info . exists ) {
MessageBox ( hwndMain , L " File does not exist. " , L " Sorry " , 0 ) ;
} else if ( info . type = = FILETYPE_DIRECTORY ) {
MessageBox ( hwndMain , L " Cannot extract directories. " , L " Sorry " , 0 ) ;
2014-03-01 13:31:23 -08:00
} else if ( W32Util : : BrowseForFileName ( false , hWnd , L " Save file as... " , 0 , L " All files \0 *.* \0 \0 " , L " " , fn ) ) {
2014-01-01 16:45:37 -08:00
FILE * fp = fopen ( fn . c_str ( ) , " wb " ) ;
u32 handle = pspFileSystem . OpenFile ( filename , FILEACCESS_READ , " " ) ;
u8 buffer [ 4096 ] ;
while ( pspFileSystem . ReadFile ( handle , buffer , sizeof ( buffer ) ) > 0 ) {
fwrite ( buffer , sizeof ( buffer ) , 1 , fp ) ;
}
pspFileSystem . CloseFile ( handle ) ;
fclose ( fp ) ;
}
}
break ;
2013-07-29 04:46:40 -04:00
case ID_DEBUG_LOG :
LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > Show ( LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > Hidden ( ) ) ;
break ;
2013-07-26 20:25:11 +08:00
2013-09-07 11:29:44 -04:00
case ID_DEBUG_IGNOREILLEGALREADS :
2013-07-29 04:46:40 -04:00
g_Config . bIgnoreBadMemAccess = ! g_Config . bIgnoreBadMemAccess ;
break ;
2013-02-19 00:44:22 +01:00
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_FULLSCREEN :
2015-02-15 23:07:24 +01:00
PostMessage ( hWnd , WM_USER_TOGGLE_FULLSCREEN , 0 , 0 ) ;
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_VERTEXCACHE :
g_Config . bVertexCache = ! g_Config . bVertexCache ;
break ;
2013-03-29 21:21:27 +01:00
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_SHOWFPS :
g_Config . iShowFPSCounter = ! g_Config . iShowFPSCounter ;
break ;
2012-11-01 16:19:01 +01:00
2013-09-11 00:19:34 +02:00
case ID_OPTIONS_TEXTUREFILTERING_AUTO : setTexFiltering ( AUTO ) ; break ;
case ID_OPTIONS_NEARESTFILTERING : setTexFiltering ( NEAREST ) ; break ;
case ID_OPTIONS_LINEARFILTERING : setTexFiltering ( LINEAR ) ; break ;
case ID_OPTIONS_LINEARFILTERING_CG : setTexFiltering ( LINEARFMV ) ; break ;
2013-06-10 23:45:12 +02:00
2014-08-08 20:51:15 +02:00
case ID_OPTIONS_BUFLINEARFILTER : setBufFilter ( SCALE_LINEAR ) ; break ;
case ID_OPTIONS_BUFNEARESTFILTER : setBufFilter ( SCALE_NEAREST ) ; break ;
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_TOPMOST :
g_Config . bTopMost = ! g_Config . bTopMost ;
W32Util : : MakeTopMost ( hWnd , g_Config . bTopMost ) ;
break ;
2013-07-06 19:08:59 +02:00
2013-10-11 14:53:25 +03:00
case ID_OPTIONS_PAUSE_FOCUS :
g_Config . bPauseOnLostFocus = ! g_Config . bPauseOnLostFocus ;
break ;
2013-07-29 04:46:40 -04:00
case ID_OPTIONS_CONTROLS :
2013-09-07 11:29:44 -04:00
NativeMessageReceived ( " control mapping " , " " ) ;
break ;
case ID_OPTIONS_MORE_SETTINGS :
NativeMessageReceived ( " settings " , " " ) ;
2013-07-29 04:46:40 -04:00
break ;
2013-06-15 11:40:31 +02:00
2013-07-29 04:46:40 -04:00
case ID_EMULATION_SOUND :
g_Config . bEnableSound = ! g_Config . bEnableSound ;
2013-12-10 19:31:29 -05:00
if ( g_Config . bEnableSound ) {
2013-12-10 19:24:50 -05:00
if ( PSP_IsInited ( ) & & ! IsAudioInitialised ( ) )
2013-08-14 14:36:54 -04:00
Audio_Init ( ) ;
}
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_HELP_OPENWEBSITE :
2013-08-26 19:00:16 +02:00
ShellExecute ( NULL , L " open " , L " http://www.ppsspp.org/ " , NULL , NULL , SW_SHOWNORMAL ) ;
break ;
case ID_HELP_BUYGOLD :
ShellExecute ( NULL , L " open " , L " http://central.ppsspp.org/buygold " , NULL , NULL , SW_SHOWNORMAL ) ;
2013-07-29 04:46:40 -04:00
break ;
2012-11-01 16:19:01 +01:00
2013-07-29 04:46:40 -04:00
case ID_HELP_OPENFORUM :
2013-08-26 19:00:16 +02:00
ShellExecute ( NULL , L " open " , L " http://forums.ppsspp.org/ " , NULL , NULL , SW_SHOWNORMAL ) ;
2013-07-29 04:46:40 -04:00
break ;
case ID_HELP_ABOUT :
DialogManager : : EnableAll ( FALSE ) ;
DialogBox ( hInst , ( LPCTSTR ) IDD_ABOUTBOX , hWnd , ( DLGPROC ) About ) ;
DialogManager : : EnableAll ( TRUE ) ;
break ;
case ID_DEBUG_TAKESCREENSHOT :
g_TakeScreenshot = true ;
break ;
default :
2013-09-03 22:06:05 -04:00
{
2013-10-12 00:14:58 -04:00
// Handle the dynamic shader switching here.
// The Menu ID is contained in wParam, so subtract
// ID_SHADERS_BASE and an additional 1 off it.
2013-11-02 20:24:19 -04:00
u32 index = ( wParam - ID_SHADERS_BASE - 1 ) ;
2014-02-16 12:25:42 -05:00
if ( index < availableShaders . size ( ) ) {
2013-10-12 00:14:58 -04:00
g_Config . sPostShaderName = availableShaders [ index ] ;
2013-10-12 13:19:23 -04:00
NativeMessageReceived ( " gpu resized " , " " ) ;
2013-10-12 00:14:58 -04:00
break ;
}
2013-09-03 22:06:05 -04:00
MessageBox ( hwndMain , L " Unimplemented " , L " Sorry " , 0 ) ;
}
2013-07-29 04:46:40 -04:00
break ;
}
2013-06-03 20:30:12 +08:00
}
2012-11-01 16:19:01 +01:00
break ;
2013-07-06 19:08:59 +02:00
2015-02-15 23:07:24 +01:00
case WM_USER_TOGGLE_FULLSCREEN :
ToggleFullscreen ( hwndMain , ! g_Config . bFullScreen ) ;
break ;
2013-07-07 10:42:39 +02:00
case WM_INPUT :
2014-01-19 12:11:08 -08:00
return WindowsRawInput : : Process ( hWnd , wParam , lParam ) ;
// TODO: Could do something useful with WM_INPUT_DEVICE_CHANGE?
2013-05-13 17:13:49 +08:00
2014-06-29 23:29:49 +02:00
// Not sure why we are actually getting WM_CHAR even though we use RawInput, but alright..
case WM_CHAR :
return WindowsRawInput : : ProcessChar ( hWnd , wParam , lParam ) ;
2013-11-30 18:21:47 -08:00
case WM_VERYSLEEPY_MSG :
switch ( wParam ) {
case VERYSLEEPY_WPARAM_SUPPORTED :
return TRUE ;
case VERYSLEEPY_WPARAM_GETADDRINFO :
{
VerySleepy_AddrInfo * info = ( VerySleepy_AddrInfo * ) lParam ;
const u8 * ptr = ( const u8 * ) info - > addr ;
2013-12-18 23:57:39 -08:00
std : : string name ;
2013-11-30 18:21:47 -08:00
2013-12-18 23:57:39 -08:00
if ( MIPSComp : : jit & & MIPSComp : : jit - > DescribeCodePtr ( ptr , name ) ) {
swprintf_s ( info - > name , L " Jit::%S " , name . c_str ( ) ) ;
return TRUE ;
2013-11-30 18:21:47 -08:00
}
2013-12-18 23:57:39 -08:00
if ( gpu & & gpu - > DescribeCodePtr ( ptr , name ) ) {
swprintf_s ( info - > name , L " GPU::%S " , name . c_str ( ) ) ;
return TRUE ;
2013-11-30 18:39:16 -08:00
}
2013-11-30 18:21:47 -08:00
}
return FALSE ;
default :
return FALSE ;
}
break ;
2012-11-01 16:19:01 +01:00
case WM_DROPFILES :
{
2013-06-08 08:32:07 +08:00
if ( ! EmuThread_Ready ( ) )
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
2012-11-01 16:19:01 +01:00
HDROP hdrop = ( HDROP ) wParam ;
int count = DragQueryFile ( hdrop , 0xFFFFFFFF , 0 , 0 ) ;
2013-07-29 04:46:40 -04:00
if ( count ! = 1 ) {
2013-08-26 19:00:16 +02:00
MessageBox ( hwndMain , L " You can only load one file at a time " , L " Error " , MB_ICONINFORMATION ) ;
2012-11-01 16:19:01 +01:00
}
else
{
TCHAR filename [ 512 ] ;
DragQueryFile ( hdrop , 0 , filename , 512 ) ;
TCHAR * type = filename + _tcslen ( filename ) - 3 ;
2013-08-20 17:21:25 +02:00
Update ( ) ;
2012-11-01 16:19:01 +01:00
2013-08-26 19:00:16 +02:00
NativeMessageReceived ( " boot " , ConvertWStringToUTF8 ( filename ) . c_str ( ) ) ;
2013-10-16 01:19:15 -07:00
Core_EnableStepping ( false ) ;
2012-11-01 16:19:01 +01:00
}
}
break ;
case WM_CLOSE :
EmuThread_Stop ( ) ;
2014-03-23 22:18:54 -07:00
InputDevice : : StopPolling ( ) ;
2014-01-19 12:11:08 -08:00
WindowsRawInput : : Shutdown ( ) ;
2012-11-01 16:19:01 +01:00
2013-01-02 22:57:57 +01:00
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
2013-01-05 19:57:06 +01:00
2012-11-01 16:19:01 +01:00
case WM_DESTROY :
2013-06-12 02:14:53 +08:00
KillTimer ( hWnd , TIMER_CURSORUPDATE ) ;
KillTimer ( hWnd , TIMER_CURSORMOVEUPDATE ) ;
2012-11-01 16:19:01 +01:00
PostQuitMessage ( 0 ) ;
break ;
2013-09-23 23:01:26 -04:00
case WM_USER + 1 :
2014-02-14 21:17:36 -08:00
if ( disasmWindow [ 0 ] )
disasmWindow [ 0 ] - > NotifyMapLoaded ( ) ;
if ( memoryWindow [ 0 ] )
memoryWindow [ 0 ] - > NotifyMapLoaded ( ) ;
2013-08-26 14:19:46 +02:00
2014-02-14 21:17:36 -08:00
if ( disasmWindow [ 0 ] )
disasmWindow [ 0 ] - > UpdateDialog ( ) ;
2012-12-22 09:21:23 -08:00
2013-03-31 18:28:13 -07:00
SetForegroundWindow ( hwndMain ) ;
2012-11-01 16:19:01 +01:00
break ;
2013-03-29 19:52:32 +01:00
2013-07-21 02:21:50 -07:00
case WM_USER_SAVESTATE_FINISH :
SetCursor ( LoadCursor ( 0 , IDC_ARROW ) ) ;
break ;
2013-03-29 19:52:32 +01:00
2013-09-01 14:06:24 -07:00
case WM_USER_UPDATE_UI :
TranslateMenus ( ) ;
Update ( ) ;
break ;
2013-09-08 00:22:38 -04:00
case WM_USER_UPDATE_SCREEN :
2014-02-12 10:36:40 +01:00
ResizeDisplay ( true ) ;
ShowScreenResolution ( ) ;
2013-09-08 00:22:38 -04:00
break ;
2013-09-13 15:17:55 -04:00
case WM_USER_WINDOW_TITLE_CHANGED :
UpdateWindowTitle ( ) ;
break ;
2014-01-19 18:44:41 -08:00
case WM_USER_BROWSE_BOOT_DONE :
BrowseAndBootDone ( ) ;
break ;
2013-03-29 19:32:20 +01:00
case WM_MENUSELECT :
2013-05-13 16:08:10 +08:00
// Unfortunately, accelerate keys (hotkeys) shares the same enabled/disabled states
// with corresponding menu items.
2013-03-29 19:32:20 +01:00
UpdateMenus ( ) ;
2014-01-20 00:57:20 -08:00
WindowsRawInput : : NotifyMenu ( ) ;
2013-03-29 19:32:20 +01:00
break ;
2012-11-01 16:19:01 +01:00
2013-05-02 20:58:10 +02:00
// Turn off the screensaver.
// Note that if there's a screensaver password, this simple method
// doesn't work on Vista or higher.
case WM_SYSCOMMAND :
{
2013-07-29 04:46:40 -04:00
switch ( wParam ) {
2013-05-02 20:58:10 +02:00
case SC_SCREENSAVE :
return 0 ;
case SC_MONITORPOWER :
return 0 ;
}
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
2012-11-01 16:19:01 +01:00
default :
return DefWindowProc ( hWnd , message , wParam , lParam ) ;
}
return 0 ;
}
2013-07-29 04:46:40 -04:00
void UpdateMenus ( ) {
2012-11-01 16:19:01 +01:00
HMENU menu = GetMenu ( GetHWND ( ) ) ;
# define CHECKITEM(item,value) CheckMenuItem(menu,item,MF_BYCOMMAND | ((value) ? MF_CHECKED : MF_UNCHECKED));
2013-09-07 11:29:44 -04:00
CHECKITEM ( ID_DEBUG_IGNOREILLEGALREADS , g_Config . bIgnoreBadMemAccess ) ;
CHECKITEM ( ID_DEBUG_SHOWDEBUGSTATISTICS , g_Config . bShowDebugStats ) ;
2012-12-21 11:08:54 +01:00
CHECKITEM ( ID_OPTIONS_HARDWARETRANSFORM , g_Config . bHardwareTransform ) ;
2013-02-13 18:21:21 +01:00
CHECKITEM ( ID_OPTIONS_STRETCHDISPLAY , g_Config . bStretchToDisplay ) ;
2013-09-07 11:29:44 -04:00
CHECKITEM ( ID_DEBUG_RUNONLOAD , g_Config . bAutoRun ) ;
2013-01-19 17:05:08 +01:00
CHECKITEM ( ID_OPTIONS_VERTEXCACHE , g_Config . bVertexCache ) ;
2013-06-19 13:08:29 +08:00
CHECKITEM ( ID_OPTIONS_SHOWFPS , g_Config . iShowFPSCounter ) ;
2014-01-25 21:41:39 +05:00
CHECKITEM ( ID_OPTIONS_FRAMESKIP_AUTO , g_Config . bAutoFrameSkip ) ;
2013-05-02 07:48:28 -07:00
CHECKITEM ( ID_OPTIONS_FRAMESKIP , g_Config . iFrameSkip ! = 0 ) ;
2013-07-20 22:03:52 +08:00
CHECKITEM ( ID_OPTIONS_VSYNC , g_Config . bVSync ) ;
2013-06-10 23:45:12 +02:00
CHECKITEM ( ID_OPTIONS_TOPMOST , g_Config . bTopMost ) ;
2013-10-11 14:53:25 +03:00
CHECKITEM ( ID_OPTIONS_PAUSE_FOCUS , g_Config . bPauseOnLostFocus ) ;
2013-05-13 16:08:10 +08:00
CHECKITEM ( ID_EMULATION_SOUND , g_Config . bEnableSound ) ;
CHECKITEM ( ID_TEXTURESCALING_DEPOSTERIZE , g_Config . bTexDeposterize ) ;
2013-09-02 18:33:00 +05:00
CHECKITEM ( ID_EMULATION_CHEATS , g_Config . bEnableCheats ) ;
2014-01-07 16:08:11 -05:00
CHECKITEM ( ID_OPTIONS_IGNOREWINKEY , g_Config . bIgnoreWindowsKey ) ;
2013-07-27 20:47:06 -04:00
2014-03-26 08:01:37 +08:00
// Disable Vertex Cache when HW T&L is disabled.
if ( ! g_Config . bHardwareTransform ) {
EnableMenuItem ( menu , ID_OPTIONS_VERTEXCACHE , MF_GRAYED ) ;
} else {
EnableMenuItem ( menu , ID_OPTIONS_VERTEXCACHE , MF_ENABLED ) ;
}
2013-09-17 13:02:34 +05:00
static const int zoomitems [ 11 ] = {
2013-09-11 00:19:34 +02:00
ID_OPTIONS_SCREENAUTO ,
2012-11-17 17:46:05 +01:00
ID_OPTIONS_SCREEN1X ,
ID_OPTIONS_SCREEN2X ,
ID_OPTIONS_SCREEN3X ,
ID_OPTIONS_SCREEN4X ,
2013-09-11 00:19:34 +02:00
ID_OPTIONS_SCREEN5X ,
2013-09-17 13:02:34 +05:00
ID_OPTIONS_SCREEN6X ,
ID_OPTIONS_SCREEN7X ,
ID_OPTIONS_SCREEN8X ,
ID_OPTIONS_SCREEN9X ,
ID_OPTIONS_SCREEN10X ,
2012-11-17 17:46:05 +01:00
} ;
2013-09-19 21:18:26 -04:00
if ( g_Config . iInternalResolution < RESOLUTION_AUTO )
g_Config . iInternalResolution = RESOLUTION_AUTO ;
2013-07-30 03:36:32 -04:00
2013-09-19 21:18:26 -04:00
else if ( g_Config . iInternalResolution > RESOLUTION_MAX )
g_Config . iInternalResolution = RESOLUTION_MAX ;
2013-07-30 03:36:32 -04:00
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( zoomitems ) ; i + + ) {
2013-09-11 00:19:34 +02:00
CheckMenuItem ( menu , zoomitems [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iInternalResolution ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
}
static const int windowSizeItems [ 4 ] = {
ID_OPTIONS_WINDOW1X ,
ID_OPTIONS_WINDOW2X ,
ID_OPTIONS_WINDOW3X ,
ID_OPTIONS_WINDOW4X ,
} ;
RECT rc ;
GetClientRect ( GetHWND ( ) , & rc ) ;
2015-05-15 18:04:05 +02:00
int checkW = g_Config . IsPortrait ( ) ? 272 : 480 ;
int checkH = g_Config . IsPortrait ( ) ? 480 : 272 ;
2013-09-11 00:19:34 +02:00
for ( int i = 0 ; i < ARRAY_SIZE ( windowSizeItems ) ; i + + ) {
2015-05-15 18:04:05 +02:00
bool check = ( i + 1 ) * checkW = = rc . right - rc . left | | ( i + 1 ) * checkH = = rc . bottom - rc . top ;
2013-09-11 00:19:34 +02:00
CheckMenuItem ( menu , windowSizeItems [ i ] , MF_BYCOMMAND | ( check ? MF_CHECKED : MF_UNCHECKED ) ) ;
2012-11-17 17:46:05 +01:00
}
2013-04-30 03:47:33 +02:00
2013-04-30 12:14:34 +02:00
static const int texscalingitems [ ] = {
2013-10-11 11:49:45 +05:00
ID_TEXTURESCALING_AUTO ,
2013-04-30 12:14:34 +02:00
ID_TEXTURESCALING_OFF ,
2013-05-01 23:55:34 +02:00
ID_TEXTURESCALING_2X ,
ID_TEXTURESCALING_3X ,
ID_TEXTURESCALING_4X ,
ID_TEXTURESCALING_5X ,
2013-04-30 03:47:33 +02:00
} ;
2013-10-11 11:49:45 +05:00
if ( g_Config . iTexScalingLevel < TEXSCALING_AUTO )
g_Config . iTexScalingLevel = TEXSCALING_AUTO ;
2013-07-30 03:36:32 -04:00
else if ( g_Config . iTexScalingLevel > TEXSCALING_MAX )
g_Config . iTexScalingLevel = TEXSCALING_MAX ;
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( texscalingitems ) ; i + + ) {
2013-10-11 11:49:45 +05:00
CheckMenuItem ( menu , texscalingitems [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iTexScalingLevel ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-05-01 23:55:34 +02:00
}
2014-01-19 21:14:21 -08:00
if ( ! gl_extensions . OES_texture_npot ) {
EnableMenuItem ( menu , ID_TEXTURESCALING_3X , MF_GRAYED ) ;
EnableMenuItem ( menu , ID_TEXTURESCALING_5X , MF_GRAYED ) ;
2014-01-20 00:42:04 -08:00
} else {
EnableMenuItem ( menu , ID_TEXTURESCALING_3X , MF_ENABLED ) ;
EnableMenuItem ( menu , ID_TEXTURESCALING_5X , MF_ENABLED ) ;
2014-01-19 21:14:21 -08:00
}
2013-05-01 23:55:34 +02:00
static const int texscalingtypeitems [ ] = {
ID_TEXTURESCALING_XBRZ ,
ID_TEXTURESCALING_HYBRID ,
2013-05-05 01:27:15 +02:00
ID_TEXTURESCALING_BICUBIC ,
ID_TEXTURESCALING_HYBRID_BICUBIC ,
2013-05-01 23:55:34 +02:00
} ;
2013-08-03 18:16:46 -04:00
if ( g_Config . iTexScalingType < TextureScaler : : XBRZ )
2013-07-30 03:36:32 -04:00
g_Config . iTexScalingType = TextureScaler : : XBRZ ;
2013-08-03 18:16:46 -04:00
else if ( g_Config . iTexScalingType > TextureScaler : : HYBRID_BICUBIC )
g_Config . iTexScalingType = TextureScaler : : HYBRID_BICUBIC ;
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( texscalingtypeitems ) ; i + + ) {
2013-05-01 23:55:34 +02:00
CheckMenuItem ( menu , texscalingtypeitems [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iTexScalingType ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-04-30 03:47:33 +02:00
}
2013-05-13 16:08:10 +08:00
2013-06-30 14:48:50 +08:00
static const int texfilteringitems [ ] = {
2013-07-01 15:42:45 -04:00
ID_OPTIONS_TEXTUREFILTERING_AUTO ,
2013-06-30 14:48:50 +08:00
ID_OPTIONS_NEARESTFILTERING ,
ID_OPTIONS_LINEARFILTERING ,
ID_OPTIONS_LINEARFILTERING_CG ,
} ;
2013-07-30 03:36:32 -04:00
if ( g_Config . iTexFiltering < AUTO )
g_Config . iTexFiltering = AUTO ;
else if ( g_Config . iTexFiltering > LINEARFMV )
g_Config . iTexFiltering = LINEARFMV ;
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( texfilteringitems ) ; i + + ) {
2013-10-05 22:59:40 -04:00
CheckMenuItem ( menu , texfilteringitems [ i ] , MF_BYCOMMAND | ( ( i + 1 ) = = g_Config . iTexFiltering ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-06-30 14:48:50 +08:00
}
2014-08-08 20:51:15 +02:00
static const int bufferfilteritems [ ] = {
ID_OPTIONS_BUFLINEARFILTER ,
ID_OPTIONS_BUFNEARESTFILTER ,
} ;
if ( g_Config . iBufFilter < SCALE_LINEAR )
g_Config . iBufFilter = SCALE_LINEAR ;
else if ( g_Config . iBufFilter > SCALE_NEAREST )
g_Config . iBufFilter = SCALE_NEAREST ;
for ( int i = 0 ; i < ARRAY_SIZE ( bufferfilteritems ) ; i + + ) {
CheckMenuItem ( menu , bufferfilteritems [ i ] , MF_BYCOMMAND | ( ( i + 1 ) = = g_Config . iBufFilter ? MF_CHECKED : MF_UNCHECKED ) ) ;
}
2013-07-21 23:17:42 +08:00
static const int renderingmode [ ] = {
ID_OPTIONS_NONBUFFEREDRENDERING ,
ID_OPTIONS_BUFFEREDRENDERING ,
ID_OPTIONS_READFBOTOMEMORYCPU ,
2013-07-22 07:33:18 +08:00
ID_OPTIONS_READFBOTOMEMORYGPU ,
2013-07-21 23:17:42 +08:00
} ;
2013-08-03 18:16:46 -04:00
if ( g_Config . iRenderingMode < FB_NON_BUFFERED_MODE )
2013-07-30 03:36:32 -04:00
g_Config . iRenderingMode = FB_NON_BUFFERED_MODE ;
2013-08-03 18:16:46 -04:00
else if ( g_Config . iRenderingMode > FB_READFBOMEMORY_GPU )
g_Config . iRenderingMode = FB_READFBOMEMORY_GPU ;
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( renderingmode ) ; i + + ) {
2013-10-05 22:00:19 -04:00
CheckMenuItem ( menu , renderingmode [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iRenderingMode ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-07-21 23:17:42 +08:00
}
2013-07-26 20:25:11 +08:00
static const int frameskipping [ ] = {
ID_OPTIONS_FRAMESKIP_0 ,
2013-09-04 21:37:41 -03:00
ID_OPTIONS_FRAMESKIP_1 ,
2013-07-26 20:25:11 +08:00
ID_OPTIONS_FRAMESKIP_2 ,
ID_OPTIONS_FRAMESKIP_3 ,
ID_OPTIONS_FRAMESKIP_4 ,
ID_OPTIONS_FRAMESKIP_5 ,
ID_OPTIONS_FRAMESKIP_6 ,
ID_OPTIONS_FRAMESKIP_7 ,
ID_OPTIONS_FRAMESKIP_8 ,
} ;
2013-08-03 18:16:46 -04:00
if ( g_Config . iFrameSkip < FRAMESKIP_OFF )
2013-07-30 03:36:32 -04:00
g_Config . iFrameSkip = FRAMESKIP_OFF ;
2013-07-30 03:38:11 -04:00
2013-08-03 18:16:46 -04:00
else if ( g_Config . iFrameSkip > FRAMESKIP_MAX )
g_Config . iFrameSkip = FRAMESKIP_MAX ;
2013-07-26 19:36:16 -04:00
for ( int i = 0 ; i < ARRAY_SIZE ( frameskipping ) ; i + + ) {
2013-10-05 22:00:19 -04:00
CheckMenuItem ( menu , frameskipping [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iFrameSkip ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-09-07 11:29:44 -04:00
}
static const int savestateSlot [ ] = {
ID_FILE_SAVESTATE_SLOT_1 ,
ID_FILE_SAVESTATE_SLOT_2 ,
ID_FILE_SAVESTATE_SLOT_3 ,
ID_FILE_SAVESTATE_SLOT_4 ,
ID_FILE_SAVESTATE_SLOT_5 ,
} ;
if ( g_Config . iCurrentStateSlot < 0 )
g_Config . iCurrentStateSlot = 0 ;
else if ( g_Config . iCurrentStateSlot > = SaveState : : SAVESTATESLOTS )
g_Config . iCurrentStateSlot = SaveState : : SAVESTATESLOTS - 1 ;
for ( int i = 0 ; i < ARRAY_SIZE ( savestateSlot ) ; i + + ) {
2013-10-05 21:49:58 -04:00
CheckMenuItem ( menu , savestateSlot [ i ] , MF_BYCOMMAND | ( ( i = = g_Config . iCurrentStateSlot ) ? MF_CHECKED : MF_UNCHECKED ) ) ;
2013-07-26 20:25:11 +08:00
}
2014-09-14 07:30:49 -04:00
if ( g_Config . iGPUBackend = = GPU_BACKEND_DIRECT3D9 ) {
EnableMenuItem ( menu , ID_OPTIONS_DIRECTX , MF_GRAYED ) ;
CheckMenuItem ( menu , ID_OPTIONS_DIRECTX , MF_CHECKED ) ;
EnableMenuItem ( menu , ID_OPTIONS_OPENGL , MF_ENABLED ) ;
} else {
EnableMenuItem ( menu , ID_OPTIONS_OPENGL , MF_GRAYED ) ;
CheckMenuItem ( menu , ID_OPTIONS_OPENGL , MF_CHECKED ) ;
EnableMenuItem ( menu , ID_OPTIONS_DIRECTX , MF_ENABLED ) ;
}
2013-10-12 01:15:47 -04:00
UpdateDynamicMenuCheckmarks ( ) ;
2013-05-13 16:08:10 +08:00
UpdateCommands ( ) ;
}
2013-08-30 20:15:13 +02:00
2013-07-29 04:46:40 -04:00
void UpdateCommands ( ) {
2013-05-13 16:08:10 +08:00
static GlobalUIState lastGlobalUIState = UISTATE_PAUSEMENU ;
static CoreState lastCoreState = CORE_ERROR ;
2014-06-22 09:38:46 +02:00
if ( lastGlobalUIState = = GetUIState ( ) & & lastCoreState = = coreState )
2013-05-13 16:08:10 +08:00
return ;
lastCoreState = coreState ;
2014-06-22 09:38:46 +02:00
lastGlobalUIState = GetUIState ( ) ;
2013-05-13 16:08:10 +08:00
HMENU menu = GetMenu ( GetHWND ( ) ) ;
2014-06-22 09:38:46 +02:00
bool isPaused = Core_IsStepping ( ) & & GetUIState ( ) = = UISTATE_INGAME ;
2013-09-16 18:08:09 -04:00
TranslateMenuItem ( ID_TOGGLE_PAUSE , L " \t F8 " , isPaused ? " Run " : " Pause " ) ;
2013-05-13 16:08:10 +08:00
2014-06-22 09:38:46 +02:00
SetIngameMenuItemStates ( GetUIState ( ) ) ;
2013-08-08 08:05:01 -07:00
EnableMenuItem ( menu , ID_DEBUG_LOG , ! g_Config . bEnableLogging ) ;
2012-11-01 16:19:01 +01:00
}
// Message handler for about box.
2013-07-29 04:46:40 -04:00
LRESULT CALLBACK About ( HWND hDlg , UINT message , WPARAM wParam , LPARAM lParam ) {
switch ( message ) {
2012-11-01 16:19:01 +01:00
case WM_INITDIALOG :
2013-03-11 22:55:29 +01:00
{
2013-07-29 04:46:40 -04:00
W32Util : : CenterWindow ( hDlg ) ;
2013-03-11 22:55:29 +01:00
HWND versionBox = GetDlgItem ( hDlg , IDC_VERSION ) ;
2014-07-10 03:19:00 -04:00
std : : string windowText = " PPSSPP " ;
windowText . append ( PPSSPP_GIT_VERSION ) ;
SetWindowText ( versionBox , ConvertUTF8ToWString ( windowText ) . c_str ( ) ) ;
2013-03-11 22:55:29 +01:00
}
2012-11-01 16:19:01 +01:00
return TRUE ;
case WM_COMMAND :
if ( LOWORD ( wParam ) = = IDOK | | LOWORD ( wParam ) = = IDCANCEL )
{
EndDialog ( hDlg , LOWORD ( wParam ) ) ;
return TRUE ;
}
break ;
}
return FALSE ;
}
2013-07-29 04:46:40 -04:00
void Update ( ) {
2014-06-29 22:13:53 +02:00
InvalidateRect ( hwndDisplay , 0 , 0 ) ;
UpdateWindow ( hwndDisplay ) ;
2012-11-01 16:19:01 +01:00
SendMessage ( hwndMain , WM_SIZE , 0 , 0 ) ;
}
2013-07-29 04:46:40 -04:00
void Redraw ( ) {
2014-06-29 22:13:53 +02:00
InvalidateRect ( hwndDisplay , 0 , 0 ) ;
2012-11-01 16:19:01 +01:00
}
2013-03-29 21:21:27 +01:00
2013-07-29 04:46:40 -04:00
void SaveStateActionFinished ( bool result , void * userdata ) {
2013-07-21 02:21:50 -07:00
PostMessage ( hwndMain , WM_USER_SAVESTATE_FINISH , 0 , 0 ) ;
2012-12-28 13:50:59 -08:00
}
2013-07-29 04:46:40 -04:00
HINSTANCE GetHInstance ( ) {
2012-11-01 16:19:01 +01:00
return hInst ;
}
2013-10-13 14:14:28 -04:00
2013-10-13 14:25:59 -04:00
void ToggleDebugConsoleVisibility ( ) {
2013-10-13 14:14:28 -04:00
if ( ! g_Config . bEnableLogging ) {
LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > Show ( false ) ;
EnableMenuItem ( menu , ID_DEBUG_LOG , MF_GRAYED ) ;
}
else {
LogManager : : GetInstance ( ) - > GetConsoleListener ( ) - > Show ( true ) ;
EnableMenuItem ( menu , ID_DEBUG_LOG , MF_ENABLED ) ;
}
}
2012-11-01 16:19:01 +01:00
}