static void HandleSizeChange(int newSizingType) { SavePosition(); Core_NotifyWindowHidden(false); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "false"); } int width = 0, height = 0; RECT rc; GetClientRect(hwndMain, &rc); width = rc.right - rc.left; height = rc.bottom - rc.top; // Moves the internal display window to match the inner size of the main window. MoveWindow(hwndDisplay, 0, 0, width, height, TRUE); // Setting pixelWidth to be too small could have odd consequences. if (width >= 4 && height >= 4) { // The framebuffer manager reads these once per frame, hopefully safe enough.. should really use a mutex or some // much better mechanism. PSP_CoreParameter().pixelWidth = width; PSP_CoreParameter().pixelHeight = height; } DEBUG_LOG(SYSTEM, "Pixel width/height: %dx%d", PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); if (UpdateScreenScale(width, height)) { NativeMessageReceived("gpu_resized", ""); } // Don't save the window state if fullscreen. if (!g_Config.bFullScreen) { g_WindowState = newSizingType; } }
void _ViewFullScreen(HWND hWnd) { // Keep in mind normal window rectangle. ::GetWindowRect(hWnd, &g_normalRC); // Remove caption and border styles. DWORD dwOldStyle = ::GetWindowLong(hWnd, GWL_STYLE); DWORD dwNewStyle = dwOldStyle & ~(WS_CAPTION | WS_THICKFRAME); ::SetWindowLong(hWnd, GWL_STYLE, dwNewStyle); // Remove the menu bar. ::SetMenu(hWnd, NULL); // Resize to full screen view. // NOTE: Use SWP_FRAMECHANGED to force redraw non-client. const int x = 0; const int y = 0; const int cx = ::GetSystemMetrics(SM_CXSCREEN); const int cy = ::GetSystemMetrics(SM_CYSCREEN); ::SetWindowPos(hWnd, HWND_TOPMOST, x, y, cx, cy, SWP_FRAMECHANGED); // Set full screen indicator. g_bFullScreen = TRUE; CorrectCursor(); ResizeDisplay(); ShowOwnedPopups(hwndMain, FALSE); UpdateScreenScale(); }
void MainUI::resizeGL(int w, int h) { bool smallWindow = g_Config.IsPortrait() ? (h < 480 + 80) : (w < 480 + 80); if (UpdateScreenScale(w, h, smallWindow)) { NativeMessageReceived("gpu resized", ""); } xscale = w / this->width(); yscale = h / this->height(); PSP_CoreParameter().pixelWidth = pixel_xres; PSP_CoreParameter().pixelHeight = pixel_yres; }
static inline void UpdateRunLoop() { UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); }
void Core_RunLoop() { while (!coreState) { time_update(); double startTime = time_now_d(); UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; // Temporary hack. if (GetAsyncKeyState(VK_ESCAPE)) { input_state.pad_buttons |= PAD_BUTTON_MENU; } host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); time_update(); // Simple throttling to not burn the GPU in the menu. #ifdef _WIN32 if (globalUIState != UISTATE_INGAME) { double sleepTime = 16.666 - (time_now_d() - startTime) * 1000.0; if (sleepTime > 0.0) Sleep((int)sleepTime); GL_SwapBuffers(); } else if (!Core_IsStepping()) { GL_SwapBuffers(); } #endif } }
void Core_RunLoop() { while (!coreState) { time_update(); double startTime = time_now_d(); UpdateScreenScale(); { { #ifdef _WIN32 lock_guard guard(input_state.lock); input_state.pad_buttons = 0; input_state.pad_lstick_x = 0; input_state.pad_lstick_y = 0; input_state.pad_rstick_x = 0; input_state.pad_rstick_y = 0; host->PollControllers(input_state); UpdateInputState(&input_state); #endif } NativeUpdate(input_state); EndInputState(&input_state); } NativeRender(); time_update(); // Simple throttling to not burn the GPU in the menu. #ifdef _WIN32 if (globalUIState != UISTATE_INGAME) { double diffTime = time_now_d() - startTime; int sleepTime = (int) (1000000.0 / 60.0) - (int) (diffTime * 1000000.0); if (sleepTime > 0) Sleep(sleepTime / 1000); GL_SwapBuffers(); } else if (!Core_IsStepping()) { GL_SwapBuffers(); } #endif } }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("EmuThread"); // Native overwrites host. Can't allow that. Host *oldHost = host; UpdateScreenScale(); NativeInit(__argc, (const char **)__argv, "1234", "1234", "1234"); Host *nativeHost = host; host = oldHost; host->UpdateUI(); //Check Colour depth HDC dc = GetDC(NULL); u32 colour_depth = GetDeviceCaps(dc, BITSPIXEL); ReleaseDC(NULL, dc); if (colour_depth != 32) { MessageBoxA(0, "Please switch your display to 32-bit colour mode", "OpenGL Error", MB_OK); ExitProcess(1); } std::string error_string; if (!host->InitGL(&error_string)) { Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str()); std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str()); MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR); ERROR_LOG(BOOT, full_error.c_str()); // No safe way out without OpenGL. ExitProcess(1); } NativeInitGraphics(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); Core_EnableStepping(FALSE); while (globalUIState != UISTATE_EXIT) { // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. if (!Core_IsActive()) UpdateUIState(UISTATE_MENU); Core_Run(); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); host->ShutdownSound(); host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGL(); _InterlockedExchange(&emuThreadReady, THREAD_END); return 0; }
unsigned int WINAPI TheThread(void *) { _InterlockedExchange(&emuThreadReady, THREAD_INIT); setCurrentThreadName("EmuThread"); std::string memstick, flash0; GetSysDirectories(memstick, flash0); // Native overwrites host. Can't allow that. Host *oldHost = host; UpdateScreenScale(); NativeInit(__argc, (const char **)__argv, memstick.c_str(), memstick.c_str(), "1234"); Host *nativeHost = host; host = oldHost; host->UpdateUI(); std::string error_string; if (!host->InitGL(&error_string)) { Reporting::ReportMessage("OpenGL init error: %s", error_string.c_str()); std::string full_error = StringFromFormat( "Failed initializing OpenGL. Try upgrading your graphics drivers.\n\nError message:\n\n%s", error_string.c_str()); MessageBoxA(0, full_error.c_str(), "OpenGL Error", MB_OK | MB_ICONERROR); ERROR_LOG(BOOT, full_error.c_str()); goto shutdown; } NativeInitGraphics(); INFO_LOG(BOOT, "Done."); _dbg_update_(); if (coreState == CORE_POWERDOWN) { INFO_LOG(BOOT, "Exit before core loop."); goto shutdown; } _InterlockedExchange(&emuThreadReady, THREAD_CORE_LOOP); if (g_Config.bBrowse) { PostMessage(MainWindow::GetHWND(), WM_COMMAND, ID_FILE_LOAD, 0); //MainWindow::BrowseAndBoot(""); } Core_EnableStepping(FALSE); while (globalUIState != UISTATE_EXIT) { Core_Run(); // We're here again, so the game quit. Restart Core_Run() which controls the UI. // This way they can load a new game. Core_UpdateState(CORE_RUNNING); } shutdown: _InterlockedExchange(&emuThreadReady, THREAD_SHUTDOWN); NativeShutdownGraphics(); host = nativeHost; NativeShutdown(); host = oldHost; host->ShutdownGL(); _InterlockedExchange(&emuThreadReady, THREAD_END); //The CPU should return when a game is stopped and cleanup should be done here, //so we can restart the plugins (or load new ones) for the next game return 0; }
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch (message) { case WM_CREATE: break; case WM_GETMINMAXINFO: { MINMAXINFO *minmax = reinterpret_cast<MINMAXINFO *>(lParam); RECT rc = { 0 }; bool portrait = g_Config.IsPortrait(); rc.right = portrait ? 272 : 480; rc.bottom = portrait ? 480 : 272; AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, TRUE); minmax->ptMinTrackSize.x = rc.right - rc.left; minmax->ptMinTrackSize.y = rc.bottom - rc.top; } return 0; case WM_ACTIVATE: { bool pause = true; if (wParam == WA_ACTIVE || wParam == WA_CLICKACTIVE) { WindowsRawInput::GainFocus(); InputDevice::GainFocus(); g_activeWindow = WINDOW_MAINWINDOW; pause = false; } if (!noFocusPause && g_Config.bPauseOnLostFocus && GetUIState() == UISTATE_INGAME) { if (pause != Core_IsStepping()) { // != is xor for bools if (disasmWindow[0]) SendMessage(disasmWindow[0]->GetDlgHandle(), WM_COMMAND, IDC_STOPGO, 0); else Core_EnableStepping(pause); } } if (wParam == WA_ACTIVE) { NativeMessageReceived("got_focus", ""); } if (wParam == WA_INACTIVE) { NativeMessageReceived("lost_focus", ""); WindowsRawInput::LoseFocus(); InputDevice::LoseFocus(); } } break; case WM_ERASEBKGND: // This window is always covered by DisplayWindow. No reason to erase. return 1; case WM_MOVE: SavePosition(); break; case WM_SIZE: switch (wParam) { case SIZE_RESTORED: case SIZE_MAXIMIZED: if (g_IgnoreWM_SIZE) { return DefWindowProc(hWnd, message, wParam, lParam); } else { SavePosition(); Core_NotifyWindowHidden(false); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "false"); } int width = 0, height = 0; RECT rc; GetClientRect(hwndMain, &rc); width = rc.right - rc.left; height = rc.bottom - rc.top; // Moves the internal display window to match the inner size of the main window. MoveWindow(hwndDisplay, 0, 0, width, height, TRUE); // Setting pixelWidth to be too small could have odd consequences. if (width >= 4 && height >= 4) { // The framebuffer manager reads these once per frame, hopefully safe enough.. should really use a mutex or some // much better mechanism. PSP_CoreParameter().pixelWidth = width; PSP_CoreParameter().pixelHeight = height; } UpdateRenderResolution(); if (UpdateScreenScale(width, height, IsWindowSmall())) { NativeMessageReceived("gpu resized", ""); } // Don't save the window state if fullscreen. if (!g_Config.bFullScreen) { g_WindowState = wParam; } } break; case SIZE_MINIMIZED: Core_NotifyWindowHidden(true); if (!g_Config.bPauseWhenMinimized) { NativeMessageReceived("window minimized", "true"); } break; default: break; } break; case WM_TIMER: // Hack: Take the opportunity to also show/hide the mouse cursor in fullscreen mode. switch (wParam) { case TIMER_CURSORUPDATE: CorrectCursor(); return 0; case TIMER_CURSORMOVEUPDATE: hideCursor = true; KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); return 0; } break; // 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) { key.keyCode = NKCODE_EXT_MOUSEWHEEL_DOWN; wheelDelta = -wheelDelta; } else { key.keyCode = NKCODE_EXT_MOUSEWHEEL_UP; } // 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); } break; case WM_COMMAND: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); MainWindowMenu_Process(hWnd, wParam); } break; case WM_USER_TOGGLE_FULLSCREEN: ToggleFullscreen(hwndMain, !g_Config.bFullScreen); break; case WM_INPUT: return WindowsRawInput::Process(hWnd, wParam, lParam); // TODO: Could do something useful with WM_INPUT_DEVICE_CHANGE? // 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); 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; std::string name; if (MIPSComp::jit && MIPSComp::jit->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"Jit::%S", name.c_str()); return TRUE; } if (gpu && gpu->DescribeCodePtr(ptr, name)) { swprintf_s(info->name, L"GPU::%S", name.c_str()); return TRUE; } } return FALSE; default: return FALSE; } break; case WM_DROPFILES: { if (!EmuThread_Ready()) return DefWindowProc(hWnd, message, wParam, lParam); HDROP hdrop = (HDROP)wParam; int count = DragQueryFile(hdrop,0xFFFFFFFF,0,0); if (count != 1) { MessageBox(hwndMain,L"You can only load one file at a time",L"Error",MB_ICONINFORMATION); } else { TCHAR filename[512]; DragQueryFile(hdrop,0,filename,512); TCHAR *type = filename+_tcslen(filename)-3; NativeMessageReceived("boot", ConvertWStringToUTF8(filename).c_str()); Core_EnableStepping(false); } } break; case WM_CLOSE: EmuThread_Stop(); InputDevice::StopPolling(); WindowsRawInput::Shutdown(); return DefWindowProc(hWnd,message,wParam,lParam); case WM_DESTROY: KillTimer(hWnd, TIMER_CURSORUPDATE); KillTimer(hWnd, TIMER_CURSORMOVEUPDATE); PostQuitMessage(0); break; case WM_USER + 1: if (disasmWindow[0]) disasmWindow[0]->NotifyMapLoaded(); if (memoryWindow[0]) memoryWindow[0]->NotifyMapLoaded(); if (disasmWindow[0]) disasmWindow[0]->UpdateDialog(); SetForegroundWindow(hwndMain); break; case WM_USER_SAVESTATE_FINISH: SetCursor(LoadCursor(0, IDC_ARROW)); break; case WM_USER_UPDATE_UI: TranslateMenus(hwndMain, menu); break; case WM_USER_UPDATE_SCREEN: ShowScreenResolution(); break; case WM_USER_WINDOW_TITLE_CHANGED: UpdateWindowTitle(); break; case WM_USER_BROWSE_BOOT_DONE: BrowseAndBootDone(); break; case WM_MENUSELECT: // Unfortunately, accelerate keys (hotkeys) shares the same enabled/disabled states // with corresponding menu items. UpdateMenus(); WindowsRawInput::NotifyMenu(); break; // 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: { switch (wParam) { case SC_SCREENSAVE: return 0; case SC_MONITORPOWER: return 0; } return DefWindowProc(hWnd, message, wParam, lParam); } default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; }