0.6.1
[libretro-ppsspp.git] / Windows / WndMainWindow.cpp
blobb6e513239d3160de5a48e6f931328d67cba2a26f
1 // NOTE: Apologies for the quality of this code, this is really from pre-opensource Dolphin - that is, 2003.
3 #include <windows.h>
4 #include <tchar.h>
5 #include "../globals.h"
7 #include "shellapi.h"
8 #include "commctrl.h"
10 #include "../Core/Debugger/SymbolMap.h"
11 #include "OpenGLBase.h"
12 #include "Debugger/Debugger_Disasm.h"
13 #include "Debugger/Debugger_MemoryDlg.h"
14 #include "main.h"
16 #include "../Core/Core.h"
17 #include "../Core/MemMap.h"
18 #include "../Core/SaveState.h"
19 #include "../Core/System.h"
20 #include "EmuThread.h"
22 #include "resource.h"
24 #include "WndMainWindow.h"
25 #include "LogManager.h"
26 #include "ConsoleListener.h"
27 #include "W32Util/DialogManager.h"
28 #include "W32Util/ShellUtil.h"
29 #include "W32Util/Misc.h"
30 #include "../Core/Config.h"
31 #include "../GPU/GPUInterface.h"
32 #include "../GPU/GPUState.h"
34 #ifdef THEMES
35 #include "XPTheme.h"
36 #endif
38 BOOL g_bFullScreen = FALSE;
39 RECT g_normalRC = {0};
41 namespace MainWindow
43 HWND hwndMain;
44 HWND hwndDisplay;
45 HWND hwndGameList;
46 HMENU menu;
47 BOOL skinMode = FALSE;
48 CoreState nextState = CORE_POWERDOWN;
50 HINSTANCE hInst;
52 //W32Util::LayeredWindow *layer;
53 #define MAX_LOADSTRING 100
54 TCHAR *szTitle = TEXT("PPSSPP");
55 TCHAR *szWindowClass = TEXT("PPSSPPWnd");
56 TCHAR *szDisplayClass = TEXT("PPSSPPDisplay");
58 // Foward declarations of functions included in this code module:
59 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
60 LRESULT CALLBACK DisplayProc(HWND, UINT, WPARAM, LPARAM);
61 LRESULT CALLBACK About(HWND, UINT, WPARAM, LPARAM);
62 LRESULT CALLBACK Controls(HWND, UINT, WPARAM, LPARAM);
64 HWND GetHWND()
66 return hwndMain;
69 HWND GetDisplayHWND()
71 return hwndDisplay;
74 void Init(HINSTANCE hInstance)
76 #ifdef THEMES
77 WTL::CTheme::IsThemingSupported();
78 #endif
79 //Register classes
80 WNDCLASSEX wcex;
81 wcex.cbSize = sizeof(WNDCLASSEX);
82 wcex.style = CS_HREDRAW | CS_VREDRAW;
83 wcex.lpfnWndProc = (WNDPROC)WndProc;
84 wcex.cbClsExtra = 0;
85 wcex.cbWndExtra = 0;
86 wcex.hInstance = hInstance;
87 wcex.hIcon = LoadIcon(hInstance, (LPCTSTR)IDI_PPSSPP);
88 wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
89 wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
90 wcex.lpszMenuName = (LPCSTR)IDR_MENU1;
91 wcex.lpszClassName = szWindowClass;
92 wcex.hIconSm = (HICON)LoadImage(hInstance, (LPCTSTR)IDI_PPSSPP, IMAGE_ICON, 16,16,LR_SHARED);
93 RegisterClassEx(&wcex);
95 wcex.style = CS_HREDRAW | CS_VREDRAW;;
96 wcex.lpfnWndProc = (WNDPROC)DisplayProc;
97 wcex.hIcon = 0;
98 wcex.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
99 wcex.lpszMenuName = 0;
100 wcex.lpszClassName = szDisplayClass;
101 wcex.hIconSm = 0;
102 RegisterClassEx(&wcex);
105 void GetWindowRectAtZoom(int zoom, RECT &rcInner, RECT &rcOuter) {
106 // GetWindowRect(hwndMain, &rcInner);
107 rcInner.left = 20;
108 rcInner.top = 120;
110 rcInner.right=480*zoom + rcInner.left;//+client edge
111 rcInner.bottom=272*zoom + rcInner.top; //+client edge
113 rcOuter=rcInner;
114 AdjustWindowRect(&rcOuter, WS_OVERLAPPEDWINDOW, TRUE);
117 void ResizeDisplay() {
118 RECT rc;
119 GetClientRect(hwndMain, &rc);
121 if ((rc.right - rc.left) == PSP_CoreParameter().pixelWidth &&
122 (rc.bottom - rc.top) == PSP_CoreParameter().pixelHeight)
123 return;
124 PSP_CoreParameter().pixelWidth = rc.right - rc.left;
125 PSP_CoreParameter().pixelHeight = rc.bottom - rc.top;
126 MoveWindow(hwndDisplay, 0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight, TRUE);
128 // round up to a zoom factor for the render size.
129 int zoom = (rc.right - rc.left + 479) / 480;
130 if (g_Config.SSAntiAliasing) zoom *= 2;
131 PSP_CoreParameter().renderWidth = 480 * zoom;
132 PSP_CoreParameter().renderHeight = 272 * zoom;
133 PSP_CoreParameter().outputWidth = 480 * zoom;
134 PSP_CoreParameter().outputHeight = 272 * zoom;
136 if (gpu)
137 gpu->Resized();
140 void SetZoom(float zoom) {
141 if (zoom < 5)
142 g_Config.iWindowZoom = (int) zoom;
143 RECT rc, rcOuter;
144 GetWindowRectAtZoom((int) zoom, rc, rcOuter);
145 MoveWindow(hwndMain, rcOuter.left, rcOuter.top, rcOuter.right - rcOuter.left, rcOuter.bottom - rcOuter.top, TRUE);
146 ResizeDisplay();
149 BOOL Show(HINSTANCE hInstance, int nCmdShow)
151 hInst = hInstance; // Store instance handle in our global variable
153 int zoom = g_Config.iWindowZoom;
154 if (zoom < 1) zoom = 1;
155 if (zoom > 4) zoom = 4;
157 RECT rc,rcOrig;
158 GetWindowRectAtZoom(zoom, rcOrig, rc);
160 u32 style = skinMode ? WS_POPUP : WS_OVERLAPPEDWINDOW;
162 hwndMain = CreateWindowEx(0,szWindowClass, "", style,
163 rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, NULL, NULL, hInstance, NULL);
164 SetPlaying(0);
165 if (!hwndMain)
166 return FALSE;
168 menu = GetMenu(hwndMain);
169 #ifdef FINAL
170 RemoveMenu(menu,2,MF_BYPOSITION);
171 RemoveMenu(menu,2,MF_BYPOSITION);
172 #endif
173 MENUINFO info;
174 ZeroMemory(&info,sizeof(MENUINFO));
175 info.cbSize = sizeof(MENUINFO);
176 info.cyMax = 0;
177 info.dwStyle = MNS_CHECKORBMP;
178 info.fMask = MIM_STYLE;
179 for (int i = 0; i < GetMenuItemCount(menu); i++)
181 SetMenuInfo(GetSubMenu(menu,i),&info);
184 hwndDisplay = CreateWindowEx(0,szDisplayClass,TEXT(""),
185 WS_CHILD|WS_VISIBLE,
186 0,0,/*rcOrig.left,rcOrig.top,*/rcOrig.right-rcOrig.left,rcOrig.bottom-rcOrig.top,hwndMain,0,hInstance,0);
188 ShowWindow(hwndMain, nCmdShow);
189 //accept dragged files
190 DragAcceptFiles(hwndMain, TRUE);
191 UpdateMenus();
193 SetFocus(hwndMain);
195 return TRUE;
198 void BrowseAndBoot(void)
200 std::string fn;
201 std::string filter = "";
203 filter += "PSP";
204 filter += "|";
205 filter += "*.pbp;*.elf;*.iso;*.cso;*.prx";
206 filter += "|";
207 filter += "|";
208 for (int i=0; i<(int)filter.length(); i++)
210 if (filter[i] == '|')
211 filter[i] = '\0';
214 if (W32Util::BrowseForFileName(true, GetHWND(), "Load File",0,filter.c_str(),"*.pbp;*.elf;*.iso;*.cso;",fn))
216 // decode the filename with fullpath
217 std::string fullpath = fn;
218 char drive[MAX_PATH];
219 char dir[MAX_PATH];
220 char fname[MAX_PATH];
221 char ext[MAX_PATH];
222 _splitpath(fullpath.c_str(), drive, dir, fname, ext);
224 // generate the mapfilename
225 std::string executable = std::string(drive) + std::string(dir) + std::string(fname) + std::string(ext);
226 std::string mapfile = std::string(drive) + std::string(dir) + std::string(fname) + std::string(".map");
228 EmuThread_Start(executable.c_str());
232 LRESULT CALLBACK DisplayProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
234 switch (message)
236 case WM_ACTIVATE:
237 break;
238 case WM_SETFOCUS:
239 break;
240 case WM_SIZE:
241 break;
243 case WM_ERASEBKGND:
244 return DefWindowProc(hWnd, message, wParam, lParam);
246 case WM_LBUTTONDOWN:
247 // Update();
248 break;
250 case WM_LBUTTONDBLCLK:
251 MessageBox(0,"Fullscreen isn't implemented yet","Sorry",0);
252 break;
253 case WM_PAINT:
254 return DefWindowProc(hWnd, message, wParam, lParam);
255 default:
256 return DefWindowProc(hWnd, message, wParam, lParam);
258 return 0;
261 LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
263 int wmId, wmEvent;
264 std::string fn;
266 switch (message)
268 case WM_CREATE:
269 break;
271 case WM_MOVE:
272 ResizeDisplay();
273 break;
275 case WM_SIZE:
276 ResizeDisplay();
277 break;
279 case WM_COMMAND:
280 wmId = LOWORD(wParam);
281 wmEvent = HIWORD(wParam);
282 // Parse the menu selections:
283 switch (wmId)
285 case ID_FILE_LOAD:
286 BrowseAndBoot();
287 break;
289 case ID_FILE_REFRESHGAMELIST:
290 break;
292 case ID_EMULATION_RUN:
293 if (g_State.bEmuThreadStarted)
295 for (int i=0; i<numCPUs; i++)
296 if (disasmWindow[i])
297 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
298 for (int i=0; i<numCPUs; i++)
299 if (disasmWindow[i])
300 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_GO, 0);
302 break;
304 case ID_EMULATION_STOP:
305 for (int i=0; i<numCPUs; i++)
306 if (disasmWindow[i])
307 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
309 Sleep(100);//UGLY wait for event instead
311 for (int i=0; i<numCPUs; i++)
312 if (disasmWindow[i])
313 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_CLOSE, 0, 0);
314 for (int i=0; i<numCPUs; i++)
315 if (memoryWindow[i])
316 SendMessage(memoryWindow[i]->GetDlgHandle(), WM_CLOSE, 0, 0);
318 EmuThread_Stop();
319 SetPlaying(0);
320 Update();
321 UpdateMenus();
322 break;
325 case ID_EMULATION_PAUSE:
326 for (int i=0; i<numCPUs; i++)
327 if (disasmWindow[i])
328 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
329 break;
331 case ID_EMULATION_SPEEDLIMIT:
332 g_Config.bSpeedLimit = !g_Config.bSpeedLimit;
333 UpdateMenus();
334 break;
336 case ID_FILE_LOADSTATEFILE:
337 if (g_State.bEmuThreadStarted)
339 nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
340 for (int i=0; i<numCPUs; i++)
341 if (disasmWindow[i])
342 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
344 if (W32Util::BrowseForFileName(true, hWnd, "Load state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn))
346 SetCursor(LoadCursor(0,IDC_WAIT));
347 SaveState::Load(fn, SaveStateActionFinished);
349 break;
351 case ID_FILE_SAVESTATEFILE:
352 if (g_State.bEmuThreadStarted)
354 nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
355 for (int i=0; i<numCPUs; i++)
356 if (disasmWindow[i])
357 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
359 if (W32Util::BrowseForFileName(false, hWnd, "Save state",0,"Save States (*.ppst)\0*.ppst\0All files\0*.*\0\0","ppst",fn))
361 SetCursor(LoadCursor(0,IDC_WAIT));
362 SaveState::Save(fn, SaveStateActionFinished);
364 break;
366 // TODO: Add UI for multiple slots
368 case ID_FILE_QUICKLOADSTATE:
369 if (g_State.bEmuThreadStarted)
371 nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
372 for (int i=0; i<numCPUs; i++)
373 if (disasmWindow[i])
374 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
376 SetCursor(LoadCursor(0,IDC_WAIT));
377 SaveState::LoadSlot(0, SaveStateActionFinished);
378 break;
380 case ID_FILE_QUICKSAVESTATE:
381 if (g_State.bEmuThreadStarted)
383 nextState = Core_IsStepping() ? CORE_STEPPING : CORE_RUNNING;
384 for (int i=0; i<numCPUs; i++)
385 if (disasmWindow[i])
386 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_STOP, 0);
388 SetCursor(LoadCursor(0,IDC_WAIT));
389 SaveState::SaveSlot(0, SaveStateActionFinished);
390 break;
392 case ID_OPTIONS_SCREEN1X:
393 SetZoom(1);
394 UpdateMenus();
395 break;
396 case ID_OPTIONS_SCREEN2X:
397 SetZoom(2);
398 UpdateMenus();
399 break;
400 case ID_OPTIONS_SCREEN3X:
401 SetZoom(3);
402 UpdateMenus();
403 break;
404 case ID_OPTIONS_SCREEN4X:
405 SetZoom(4);
406 UpdateMenus();
407 break;
409 case ID_OPTIONS_BUFFEREDRENDERING:
410 g_Config.bBufferedRendering = !g_Config.bBufferedRendering;
411 UpdateMenus();
412 break;
414 case ID_OPTIONS_SHOWDEBUGSTATISTICS:
415 g_Config.bShowDebugStats = !g_Config.bShowDebugStats;
416 UpdateMenus();
417 break;
419 case ID_OPTIONS_HARDWARETRANSFORM:
420 g_Config.bHardwareTransform = !g_Config.bHardwareTransform;
421 UpdateMenus();
422 break;
424 case ID_FILE_EXIT:
425 DestroyWindow(hWnd);
426 break;
428 case ID_CPU_DYNAREC:
429 g_Config.iCpuCore = CPU_JIT;
430 UpdateMenus();
431 break;
432 case ID_CPU_INTERPRETER:
433 g_Config.iCpuCore = CPU_INTERPRETER;
434 UpdateMenus();
435 break;
436 case ID_CPU_FASTINTERPRETER:
437 g_Config.iCpuCore = CPU_FASTINTERPRETER;
438 UpdateMenus();
439 break;
441 case ID_EMULATION_RUNONLOAD:
442 g_Config.bAutoRun = !g_Config.bAutoRun;
443 UpdateMenus();
444 break;
446 case ID_DEBUG_DUMPNEXTFRAME:
447 gpu->DumpNextFrame();
448 break;
450 case ID_DEBUG_LOADMAPFILE:
451 if (W32Util::BrowseForFileName(true, hWnd, "Load .MAP",0,"Maps\0*.map\0All files\0*.*\0\0","map",fn))
453 symbolMap.LoadSymbolMap(fn.c_str());
454 // HLE_PatchFunctions();
455 for (int i=0; i<numCPUs; i++)
456 if (disasmWindow[i])
457 disasmWindow[i]->NotifyMapLoaded();
458 for (int i=0; i<numCPUs; i++)
459 if (memoryWindow[i])
460 memoryWindow[i]->NotifyMapLoaded();
462 break;
463 case ID_DEBUG_SAVEMAPFILE:
464 if (W32Util::BrowseForFileName(false, hWnd, "Save .MAP",0,"Maps\0*.map\0All files\0*.*\0\0","map",fn))
465 symbolMap.SaveSymbolMap(fn.c_str());
466 break;
468 case ID_DEBUG_RESETSYMBOLTABLE:
469 symbolMap.ResetSymbolMap();
470 for (int i=0; i<numCPUs; i++)
471 if (disasmWindow[i])
472 disasmWindow[i]->NotifyMapLoaded();
473 for (int i=0; i<numCPUs; i++)
474 if (memoryWindow[i])
475 memoryWindow[i]->NotifyMapLoaded();
476 break;
477 case ID_DEBUG_DISASSEMBLY:
478 if (disasmWindow[0])
479 disasmWindow[0]->Show(true);
480 break;
481 case ID_DEBUG_MEMORYVIEW:
482 if (memoryWindow[0])
483 memoryWindow[0]->Show(true);
484 break;
485 case ID_DEBUG_LOG:
486 LogManager::GetInstance()->GetConsoleListener()->Show(LogManager::GetInstance()->GetConsoleListener()->Hidden());
487 break;
489 case ID_OPTIONS_IGNOREILLEGALREADS:
490 g_Config.bIgnoreBadMemAccess = !g_Config.bIgnoreBadMemAccess;
491 UpdateMenus();
492 break;
494 case ID_OPTIONS_FULLSCREEN:
495 if(g_bFullScreen) {
496 _ViewNormal(hWnd);
497 } else {
498 _ViewFullScreen(hWnd);
500 UpdateMenus();
501 break;
503 case ID_OPTIONS_WIREFRAME:
504 g_Config.bDrawWireframe = !g_Config.bDrawWireframe;
505 UpdateMenus();
506 break;
507 case ID_OPTIONS_VERTEXCACHE:
508 g_Config.bVertexCache = !g_Config.bVertexCache;
509 UpdateMenus();
510 break;
511 case ID_OPTIONS_DISPLAYRAWFRAMEBUFFER:
512 g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer;
513 UpdateMenus();
514 break;
515 case ID_OPTIONS_FASTMEMORY:
516 g_Config.bFastMemory = !g_Config.bFastMemory;
517 UpdateMenus();
518 break;
519 case ID_OPTIONS_USEVBO:
520 g_Config.bUseVBO = !g_Config.bUseVBO;
521 UpdateMenus();
522 break;
523 case ID_OPTIONS_LINEARFILTERING:
524 g_Config.bLinearFiltering = !g_Config.bLinearFiltering;
525 UpdateMenus();
526 break;
527 case ID_OPTIONS_SIMPLE2XSSAA:
528 g_Config.SSAntiAliasing = !g_Config.SSAntiAliasing;
529 UpdateMenus();
530 break;
531 case ID_OPTIONS_DISABLEG3DLOG:
532 g_Config.bDisableG3DLog = !g_Config.bDisableG3DLog;
533 if (!g_Config.bDisableG3DLog )
534 LogManager::GetInstance()->SetEnable(LogTypes::G3D, true);
535 else
536 LogManager::GetInstance()->SetEnable(LogTypes::G3D, false);
537 UpdateMenus();
538 break;
539 case ID_OPTIONS_CONTROLS:
540 DialogManager::EnableAll(FALSE);
541 DialogBox(hInst, (LPCTSTR)IDD_CONTROLS, hWnd, (DLGPROC)Controls);
542 DialogManager::EnableAll(TRUE);
543 break;
545 case ID_HELP_OPENWEBSITE:
546 ShellExecute(NULL, "open", "http://www.ppsspp.org/", NULL, NULL, SW_SHOWNORMAL);
547 break;
549 case ID_HELP_ABOUT:
550 DialogManager::EnableAll(FALSE);
551 DialogBox(hInst, (LPCTSTR)IDD_ABOUTBOX, hWnd, (DLGPROC)About);
552 DialogManager::EnableAll(TRUE);
553 break;
555 default:
557 MessageBox(hwndMain,"Unimplemented","Sorry",0);
559 break;
561 break;
562 case WM_KEYDOWN:
564 static int mojs=0;
565 mojs ^= 1;
566 //SetSkinMode(mojs);
568 break;
569 case WM_DROPFILES:
571 HDROP hdrop = (HDROP)wParam;
572 int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0);
573 if (count != 1)
575 MessageBox(hwndMain,"You can only load one file at a time","Error",MB_ICONINFORMATION);
577 else
579 TCHAR filename[512];
580 DragQueryFile(hdrop,0,filename,512);
581 TCHAR *type = filename+_tcslen(filename)-3;
583 TBootFileType t;
584 if (strcmp(type,"bin")==0)
585 t=BOOT_BIN;
586 else if (strcmp(type,"elf")==0)
587 t=BOOT_ELF;
588 else if (strcmp(type,"dol")==0)
589 t=BOOT_DOL;
590 else
592 MessageBox(hwndMain,"Not a runnable Gamecube file","Error",MB_ICONERROR);
593 break;
595 CCore::Start(0,filename,t);
598 if (g_State.bEmuThreadStarted)
600 SendMessage(hWnd, WM_COMMAND, ID_EMULATION_STOP, 0);
603 MainWindow::SetPlaying(filename);
604 MainWindow::Update();
605 MainWindow::UpdateMenus();
607 EmuThread_Start(filename);
610 break;
612 case WM_CLOSE:
613 Sleep(100);//UGLY wait for event instead
614 EmuThread_Stop();
617 if (g_Config.bConfirmOnQuit && CCore::IsRunning())
619 if (IDNO==MessageBox(hwndMain,"A game is in progress. Are you sure you want to exit?","Are you sure?",MB_YESNO|MB_ICONQUESTION))
620 return 1;//or 1?
621 else
622 return DefWindowProc(hWnd,message,wParam,lParam);
623 break;
625 else
627 return DefWindowProc(hWnd,message,wParam,lParam);
629 case WM_DESTROY:
630 PostQuitMessage(0);
631 break;
632 case WM_NCHITTEST:
633 if (skinMode)
634 return HTCAPTION;
635 else
636 return DefWindowProc(hWnd,message,wParam,lParam);
638 case WM_USER+1:
639 disasmWindow[0] = new CDisasm(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
640 DialogManager::AddDlg(disasmWindow[0]);
641 disasmWindow[0]->Show(g_Config.bShowDebuggerOnLoad);
642 if (g_Config.bFullScreen) _ViewFullScreen(hWnd);
643 memoryWindow[0] = new CMemoryDlg(MainWindow::GetHInstance(), MainWindow::GetHWND(), currentDebugMIPS);
644 DialogManager::AddDlg(memoryWindow[0]);
645 if (disasmWindow[0])
646 disasmWindow[0]->NotifyMapLoaded();
647 if (memoryWindow[0])
648 memoryWindow[0]->NotifyMapLoaded();
650 if (nextState == CORE_RUNNING)
651 PostMessage(hwndMain, WM_COMMAND, ID_EMULATION_RUN, 0);
652 UpdateMenus();
653 break;
655 default:
656 return DefWindowProc(hWnd, message, wParam, lParam);
658 return 0;
662 void UpdateMenus()
664 HMENU menu = GetMenu(GetHWND());
665 #define CHECKITEM(item,value) CheckMenuItem(menu,item,MF_BYCOMMAND | ((value) ? MF_CHECKED : MF_UNCHECKED));
667 CHECKITEM(ID_EMULATION_SPEEDLIMIT,g_Config.bSpeedLimit);
668 // CHECK(ID_OPTIONS_ENABLEFRAMEBUFFER,g_Config.bEnableFrameBuffer);
669 // CHECK(ID_OPTIONS_EMULATESYSCALL,g_bEmulateSyscall);
670 CHECKITEM(ID_OPTIONS_DISPLAYRAWFRAMEBUFFER, g_Config.bDisplayFramebuffer);
671 CHECKITEM(ID_OPTIONS_IGNOREILLEGALREADS,g_Config.bIgnoreBadMemAccess);
672 CHECKITEM(ID_CPU_INTERPRETER,g_Config.iCpuCore == CPU_INTERPRETER);
673 CHECKITEM(ID_CPU_FASTINTERPRETER,g_Config.iCpuCore == CPU_FASTINTERPRETER);
674 CHECKITEM(ID_CPU_DYNAREC,g_Config.iCpuCore == CPU_JIT);
675 CHECKITEM(ID_OPTIONS_BUFFEREDRENDERING, g_Config.bBufferedRendering);
676 CHECKITEM(ID_OPTIONS_SHOWDEBUGSTATISTICS, g_Config.bShowDebugStats);
677 CHECKITEM(ID_OPTIONS_WIREFRAME, g_Config.bDrawWireframe);
678 CHECKITEM(ID_OPTIONS_HARDWARETRANSFORM, g_Config.bHardwareTransform);
679 CHECKITEM(ID_OPTIONS_FASTMEMORY, g_Config.bFastMemory);
680 CHECKITEM(ID_OPTIONS_LINEARFILTERING, g_Config.bLinearFiltering);
681 CHECKITEM(ID_OPTIONS_SIMPLE2XSSAA, g_Config.SSAntiAliasing);
682 CHECKITEM(ID_EMULATION_RUNONLOAD, g_Config.bAutoRun);
683 CHECKITEM(ID_OPTIONS_USEVBO, g_Config.bUseVBO);
684 CHECKITEM(ID_OPTIONS_DISABLEG3DLOG, g_Config.bDisableG3DLog);
685 CHECKITEM(ID_OPTIONS_VERTEXCACHE, g_Config.bVertexCache);
687 UINT enable = !Core_IsStepping() ? MF_GRAYED : MF_ENABLED;
688 EnableMenuItem(menu,ID_EMULATION_RUN, g_State.bEmuThreadStarted ? enable : MF_GRAYED);
689 EnableMenuItem(menu,ID_EMULATION_PAUSE, g_State.bEmuThreadStarted ? !enable : MF_GRAYED);
690 EnableMenuItem(menu,ID_EMULATION_RESET, g_State.bEmuThreadStarted ? MF_ENABLED : MF_GRAYED);
692 enable = g_State.bEmuThreadStarted ? MF_GRAYED : MF_ENABLED;
693 EnableMenuItem(menu,ID_FILE_LOAD,enable);
694 EnableMenuItem(menu,ID_FILE_SAVESTATEFILE,!enable);
695 EnableMenuItem(menu,ID_FILE_LOADSTATEFILE,!enable);
696 EnableMenuItem(menu,ID_FILE_QUICKSAVESTATE,!enable);
697 EnableMenuItem(menu,ID_FILE_QUICKLOADSTATE,!enable);
698 EnableMenuItem(menu,ID_CPU_DYNAREC,enable);
699 EnableMenuItem(menu,ID_CPU_INTERPRETER,enable);
700 EnableMenuItem(menu,ID_CPU_FASTINTERPRETER,enable);
701 EnableMenuItem(menu,ID_DVD_INSERTISO,enable);
702 EnableMenuItem(menu,ID_FILE_BOOTBIOS,enable);
703 EnableMenuItem(menu,ID_EMULATION_STOP,!enable);
704 EnableMenuItem(menu,ID_OPTIONS_SETTINGS,enable);
705 EnableMenuItem(menu,ID_PLUGINS_CHOOSEPLUGINS,enable);
706 EnableMenuItem(menu,ID_OPTIONS_SIMPLE2XSSAA,enable);
708 const int zoomitems[4] = {
709 ID_OPTIONS_SCREEN1X,
710 ID_OPTIONS_SCREEN2X,
711 ID_OPTIONS_SCREEN3X,
712 ID_OPTIONS_SCREEN4X,
714 for (int i = 0; i < 4; i++) {
715 CheckMenuItem(menu, zoomitems[i], MF_BYCOMMAND | ((i == g_Config.iWindowZoom - 1) ? MF_CHECKED : MF_UNCHECKED));
720 // Message handler for about box.
721 LRESULT CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
723 switch (message)
725 case WM_INITDIALOG:
726 W32Util::CenterWindow(hDlg);
727 return TRUE;
729 case WM_COMMAND:
730 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
732 EndDialog(hDlg, LOWORD(wParam));
733 return TRUE;
735 break;
737 return FALSE;
740 const char *controllist[] = {
741 "Start\tSpace",
742 "Select\tV",
743 "Square\tA",
744 "Triangle\tS",
745 "Circle\tX",
746 "Cross\tZ",
747 "Left Trigger\tQ",
748 "Right Trigger\tW",
749 "Up\tArrow Up",
750 "Down\tArrow Down",
751 "Left\tArrow Left",
752 "Right\tArrow Right",
753 "Analog Up\tI",
754 "Analog Down\tK",
755 "Analog Left\tJ",
756 "Analog Right\tL",
758 // Message handler for about box.
759 LRESULT CALLBACK Controls(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
761 switch (message)
763 case WM_INITDIALOG:
764 W32Util::CenterWindow(hDlg);
766 // TODO: connect to keyboard device instead
767 HWND list = GetDlgItem(hDlg, IDC_LISTCONTROLS);
768 int stops[1] = {80};
769 SendMessage(list, LB_SETTABSTOPS, 1, (LPARAM)stops);
770 for (int i = 0; i < sizeof(controllist)/sizeof(controllist[0]); i++) {
771 SendMessage(list, LB_INSERTSTRING, -1, (LPARAM)controllist[i]);
774 return TRUE;
776 case WM_COMMAND:
777 if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
779 EndDialog(hDlg, LOWORD(wParam));
780 return TRUE;
782 break;
784 return FALSE;
787 void Update()
789 InvalidateRect(hwndDisplay,0,0);
790 UpdateWindow(hwndDisplay);
791 SendMessage(hwndMain,WM_SIZE,0,0);
794 void Redraw()
796 InvalidateRect(hwndDisplay,0,0);
798 void _ViewNormal(HWND hWnd)
800 // put caption and border styles back
801 DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE);
802 DWORD dwNewStyle = dwOldStyle | WS_CAPTION | WS_THICKFRAME;
803 ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
805 // put back the menu bar
806 ::SetMenu(hWnd, menu);
808 // resize to normal view
809 // NOTE: use SWP_FRAMECHANGED to force redraw non-client
810 const int x = g_normalRC.left;
811 const int y = g_normalRC.top;
812 const int cx = g_normalRC.right - g_normalRC.left;
813 const int cy = g_normalRC.bottom - g_normalRC.top;
814 ::SetWindowPos(hWnd, HWND_NOTOPMOST, x, y, cx, cy, SWP_FRAMECHANGED);
816 // reset full screen indicator
817 g_bFullScreen = FALSE;
818 ResizeDisplay();
821 void _ViewFullScreen(HWND hWnd)
823 // keep in mind normal window rectangle
824 ::GetWindowRect(hWnd, &g_normalRC);
826 // remove caption and border styles
827 DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE);
828 DWORD dwNewStyle = dwOldStyle & ~(WS_CAPTION | WS_THICKFRAME);
829 ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle);
831 // remove the menu bar
832 ::SetMenu(hWnd, NULL);
834 // resize to full screen view
835 // NOTE: use SWP_FRAMECHANGED to force redraw non-client
836 const int x = 0;
837 const int y = 0;
838 const int cx = ::GetSystemMetrics(SM_CXSCREEN);
839 const int cy = ::GetSystemMetrics(SM_CYSCREEN);
840 ::SetWindowPos(hWnd, HWND_TOPMOST, x, y, cx, cy, SWP_FRAMECHANGED);
842 // set full screen indicator
843 g_bFullScreen = TRUE;
844 ResizeDisplay();
847 void SetPlaying(const char *text)
849 if (text == 0)
850 SetWindowText(hwndMain, "PPSSPP " PPSSPP_VERSION_STR);
851 else
853 char temp[256];
854 sprintf(temp, "%s - %s", text, "PPSSPP " PPSSPP_VERSION_STR);
855 SetWindowText(hwndMain,temp);
859 void SaveStateActionFinished(bool result, void *userdata)
861 // TODO: Improve messaging?
862 if (!result)
863 MessageBox(0, "Savestate failure. Please try again later.", "Sorry", MB_OK);
864 SetCursor(LoadCursor(0, IDC_ARROW));
866 if (g_State.bEmuThreadStarted && nextState == CORE_RUNNING)
868 for (int i=0; i<numCPUs; i++)
869 if (disasmWindow[i])
870 SendMessage(disasmWindow[i]->GetDlgHandle(), WM_COMMAND, IDC_GO, 0);
874 void SetNextState(CoreState state)
876 nextState = state;
879 HINSTANCE GetHInstance()
881 return hInst;