diff --git a/Core/Config.cpp b/Core/Config.cpp index 0e58d80a31..5e0c52fd71 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -1254,11 +1254,13 @@ void Config::Reload() { // really think of any other legit uses). void Config::UpdateIniLocation(const char *iniFileName, const char *controllerIniFilename) { const bool useIniFilename = iniFileName != nullptr && strlen(iniFileName) > 0; + const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; + const char *ppssppIniFilename = IsVREnabled() ? "ppssppvr.ini" : "ppsspp.ini"; + const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini"; + bool exists; iniFilename_ = FindConfigFile(searchPath_, useIniFilename ? iniFileName : ppssppIniFilename, &exists); - const bool useControllerIniFilename = controllerIniFilename != nullptr && strlen(controllerIniFilename) > 0; - const char *controlsIniFilename = IsVREnabled() ? "controlsvr.ini" : "controls.ini"; controllerIniFilename_ = FindConfigFile(searchPath_, useControllerIniFilename ? controllerIniFilename : controlsIniFilename, &exists); } diff --git a/Windows/MainWindow.cpp b/Windows/MainWindow.cpp index eb60d4fcc1..f831a7af43 100644 --- a/Windows/MainWindow.cpp +++ b/Windows/MainWindow.cpp @@ -507,7 +507,7 @@ namespace MainWindow { WINDOWPLACEMENT placement{sizeof(WINDOWPLACEMENT)}; if ((g_Config.iWindowX == -1 && g_Config.iWindowY == -1) || g_Config.iWindowWidth < 20 || g_Config.iWindowHeight < 20) { - RECT rc = DetermineDefaultWindowRectangle(); + const RECT rc = DetermineDefaultWindowRectangle(); // Should be a first boot, or just bad parameters. Reset. g_Config.iWindowSizeState = (int)WindowSizeState::Normal; g_Config.iWindowX = rc.left; @@ -1114,6 +1114,11 @@ namespace MainWindow { DestroyWindow(hWnd); break; + case WM_USER_SHOW_DISASM: + CreateDisasmWindow(); + disasmWindow->Show(g_Config.bShowDebuggerOnLoad, false); + break; + case WM_INITMENUPOPUP: // Called when a menu or submenu is about to be opened. UpdateMenus((HMENU)wParam); diff --git a/Windows/MainWindow.h b/Windows/MainWindow.h index c4ebf26f0d..3adfccecf3 100644 --- a/Windows/MainWindow.h +++ b/Windows/MainWindow.h @@ -21,6 +21,7 @@ namespace MainWindow WM_USER_SWITCHUMD_UPDATED = WM_USER + 107, WM_USER_RUN_CALLBACK = WM_USER + 108, WM_USER_DESTROY = WM_USER + 109, + WM_USER_SHOW_DISASM = WM_USER + 110, }; enum { diff --git a/Windows/main.cpp b/Windows/main.cpp index fe7610d58c..67abc9f431 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -22,7 +22,7 @@ #include #include #include - +#include #include #include #include @@ -104,6 +104,7 @@ extern "C" { extern "C" { __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } + #if PPSSPP_API(ANY_GL) CGEDebugger* geDebuggerWindow = nullptr; #endif @@ -112,19 +113,19 @@ CDisasm *disasmWindow = nullptr; CMemoryDlg *memoryWindow = nullptr; CVFPUDlg *vfpudlg = nullptr; -static std::string langRegion; -static std::string osName; -static std::string osVersion; -static std::string gpuDriverVersion; -static std::string computerName; +static std::string g_langRegion; +static std::string g_osName; +static std::string g_osVersionString; +static std::string g_gpuDriverVersion; +static std::string g_computerName; -static std::string restartArgs; +static std::string g_restartArgs; int g_activeWindow = 0; int g_lastNumInstances = 0; -float mouseDeltaX_ = 0; -float mouseDeltaY_ = 0; +float g_mouseDeltaX = 0; +float g_mouseDeltaY = 0; static double g_lastActivity = 0.0; static double g_lastKeepAwake = 0.0; @@ -161,26 +162,27 @@ void System_Vibrate(int length_ms) { } static void AddDebugRestartArgs() { - if (g_logManager.GetConsoleListener()->IsOpen()) - restartArgs += " -l"; + if (g_logManager.GetConsoleListener()->IsOpen()) { + g_restartArgs += " -l"; + } } static void PollControllers() { // Disabled by default, needs a workaround to map to psp keys. if (g_Config.bMouseControl) { - NativeMouseDelta(mouseDeltaX_, mouseDeltaY_); + NativeMouseDelta(g_mouseDeltaX, g_mouseDeltaY); } - mouseDeltaX_ *= g_Config.fMouseSmoothing; - mouseDeltaY_ *= g_Config.fMouseSmoothing; + g_mouseDeltaX *= g_Config.fMouseSmoothing; + g_mouseDeltaY *= g_Config.fMouseSmoothing; - HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = mouseDeltaX_; - HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = mouseDeltaY_; + HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_X] = g_mouseDeltaX; + HLEPlugins::PluginDataAxis[JOYSTICK_AXIS_MOUSE_REL_Y] = g_mouseDeltaY; } // Adapted mostly as-is from http://www.gamedev.net/topic/495075-how-to-retrieve-info-about-videocard/?view=findpost&p=4229170 // so credit goes to that post's author, and in turn, the author of the site mentioned in that post (which seems to be down?). -std::string GetVideoCardDriverVersion() { +static std::string GetVideoCardDriverVersion() { std::string retvalue = ""; HRESULT hr; @@ -240,11 +242,11 @@ std::string System_GetProperty(SystemProperty prop) { static bool hasCheckedGPUDriverVersion = false; switch (prop) { case SYSPROP_NAME: - return osName; + return g_osName; case SYSPROP_SYSTEMBUILD: - return osVersion; + return g_osVersionString; case SYSPROP_LANGREGION: - return langRegion; + return g_langRegion; case SYSPROP_CLIPBOARD_TEXT: { std::string retval; @@ -263,24 +265,24 @@ std::string System_GetProperty(SystemProperty prop) { case SYSPROP_GPUDRIVER_VERSION: if (!hasCheckedGPUDriverVersion) { hasCheckedGPUDriverVersion = true; - gpuDriverVersion = GetVideoCardDriverVersion(); + g_gpuDriverVersion = GetVideoCardDriverVersion(); } - return gpuDriverVersion; + return g_gpuDriverVersion; case SYSPROP_BUILD_VERSION: return PPSSPP_GIT_VERSION; case SYSPROP_USER_DOCUMENTS_DIR: return Path(W32Util::UserDocumentsPath()).ToString(); // this'll reverse the slashes. case SYSPROP_COMPUTER_NAME: - if (computerName.empty()) { + if (g_computerName.empty()) { wchar_t nameBuf[MAX_COMPUTERNAME_LENGTH + 1]; DWORD size = ARRAY_SIZE(nameBuf); if (GetComputerNameW(nameBuf, &size)) { - computerName = ConvertWStringToUTF8(std::wstring(nameBuf, size)); + g_computerName = ConvertWStringToUTF8(std::wstring(nameBuf, size)); } else { - computerName = "(N/A)"; + g_computerName = "(N/A)"; } } - return computerName; + return g_computerName; default: return ""; } @@ -654,8 +656,8 @@ bool System_MakeRequest(SystemRequestType type, int requestId, const std::string return true; case SystemRequestType::RESTART_APP: { - restartArgs = param1; - if (!restartArgs.empty()) + g_restartArgs = param1; + if (!g_restartArgs.empty()) AddDebugRestartArgs(); if (false) { // This doesn't really work anymore: System_GetPropertyBool(SYSPROP_DEBUGGER_PRESENT)) { PostMessage(MainWindow::GetHWND(), MainWindow::WM_USER_RESTART_EMUTHREAD, 0, 0); @@ -908,10 +910,10 @@ static bool DetectVulkanInExternalProcess() { std::vector GetWideCmdLine() { wchar_t **wargv; int wargc = -1; - if (!restartArgs.empty()) { - std::wstring wargs = ConvertUTF8ToWString("PPSSPP " + restartArgs); + if (!g_restartArgs.empty()) { + std::wstring wargs = ConvertUTF8ToWString("PPSSPP " + g_restartArgs); wargv = CommandLineToArgvW(wargs.c_str(), &wargc); - restartArgs.clear(); + g_restartArgs.clear(); } else { wargv = CommandLineToArgvW(GetCommandLineW(), &wargc); } @@ -1016,13 +1018,125 @@ static void WinMainCleanup() { if (g_Config.bUpdatedInstanceCounter) { ShutdownInstanceCounter(); } - W32Util::ExitAndRestart(!restartArgs.empty(), restartArgs); + W32Util::ExitAndRestart(!g_restartArgs.empty(), g_restartArgs); + } +} + +struct CommandLineOptions { + std::optional fullscreen; + std::optional gpuBackend; + std::optional softwareRendering; + std::optional enableLogging; + +#ifndef _DEBUG + bool showLogWindow = false; +#else + bool showLogWindow = true; +#endif + bool debugLogLevel = false; + std::string configFilename = ""; + std::string controlsConfigFilename = ""; + + + bool optionS = true; // a legacy option + + void Parse(int argc, const char *argv[]); + void ApplyToConfig() const; +}; + +void CommandLineOptions::Parse(int argc, const char *argv[]) { + constexpr std::string_view gpuBackendStr = "--graphics="; + constexpr std::string_view configOption = "--config="; + constexpr std::string_view controlsOption = "--controlconfig="; + +#ifdef _DEBUG + enableLogging = true; +#endif + + // The rest is handled in NativeInit(). + for (size_t i = 1; i < argc; ++i) { + const size_t len = strlen(argv[i]); + if (argv[i][0] != '-' || len < 2) { + continue; + } + + // single char commands, like -l, -s, -d + if (len == 2) { + switch (argv[i][1]) { + case 'l': + showLogWindow = true; + enableLogging = true; + break; + case 's': + optionS = true; + break; + case 'd': + debugLogLevel = true; + break; + } + } + + // Simple bool commands + + // NOTE: We need to parse --fullscreen early, before we create the window. + if (equals(argv[i], "--fullscreen")) { + fullscreen = true; + } else if (equals(argv[i], "--windowed")) { + fullscreen = false; + } + // Commands with parameters. TODO: Should support both space and equals, like --config=foo.ini and --config foo.ini + if (startsWith(argv[i], gpuBackendStr)) { + const std::string_view restOfOption = argv[i] + gpuBackendStr.size(); + // Force software rendering off, as picking gles implies HW acceleration. + // We could add more options for software such as "software-gles", + // "software-vulkan" and "software-d3d11", or something similar. + // For now, software rendering force-activates OpenGL. + if (restOfOption == "directx11" || restOfOption == "d3d11") { + gpuBackend = GPUBackend::DIRECT3D11; + softwareRendering = false; + } else if (restOfOption == "gles") { + gpuBackend = GPUBackend::OPENGL; + softwareRendering = false; + } else if (restOfOption == "vulkan") { + gpuBackend = GPUBackend::VULKAN; + softwareRendering = false; + } else if (restOfOption == "software") { + gpuBackend = GPUBackend::OPENGL; + softwareRendering = true; + } + } else if (startsWith(argv[i], configOption)) { + configFilename = std::string(argv[i] + configOption.size()); + } else if (startsWith(argv[i], controlsOption)) { + controlsConfigFilename = std::string(argv[i] + controlsOption.size()); + } + } +} + +void CommandLineOptions::ApplyToConfig() const { + if (fullscreen.has_value()) { + g_Config.bFullScreen = fullscreen.value(); + g_Config.DoNotSaveSetting(&g_Config.bFullScreen); + } + if (gpuBackend.has_value()) { + g_Config.iGPUBackend = (int)gpuBackend.value(); + g_Config.DoNotSaveSetting(&g_Config.iGPUBackend); + } + if (softwareRendering.has_value()) { + g_Config.bSoftwareRendering = softwareRendering.value(); + g_Config.DoNotSaveSetting(&g_Config.bSoftwareRendering); + } + if (enableLogging.has_value()) { + g_Config.bEnableLogging = enableLogging.value(); + g_Config.DoNotSaveSetting(&g_Config.bEnableLogging); + } + if (optionS) { + g_Config.bAutoRun = false; + g_Config.bSaveSettings = false; } } int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLine, int iCmdShow) { const std::vector wideArgs = GetWideCmdLine(); - // Check for the Vulkan workaround before any serious init. for (size_t i = 1; i < wideArgs.size(); ++i) { if (wideArgs[i][0] == L'-') { @@ -1039,51 +1153,42 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } } + // We convert command line arguments to UTF-8. + std::vector argsUTF8; + for (const auto &string : wideArgs) { + argsUTF8.push_back(ConvertWStringToUTF8(string)); + } + std::vector args; + for (const auto &string : argsUTF8) { + args.push_back(string.c_str()); + } + + // args provide argc and argv. + CommandLineOptions cmdLineOptions; + cmdLineOptions.Parse((int)args.size(), args.data()); + + if (iCmdShow == SW_MAXIMIZE) { + // Consider this to mean --fullscreen. I guess frontends might use it? + cmdLineOptions.fullscreen = true; + } + SetCurrentThreadName("Main"); TimeInit(); WinMainInit(); -#ifndef _DEBUG - bool showLog = false; -#else - bool showLog = true; -#endif - const Path &exePath = File::GetExeDirectory(); g_VFS.Register("", new DirectoryReader(exePath / "assets")); g_VFS.Register("", new DirectoryReader(exePath)); - langRegion = GetDefaultLangRegion(); - osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); + g_langRegion = GetDefaultLangRegion(); + g_osName = GetWindowsVersion() + " " + GetWindowsSystemArchitecture(); // OS Build uint32_t outMajor = 0, outMinor = 0, outBuild = 0; if (GetVersionFromKernel32(outMajor, outMinor, outBuild)) { // Builds with (service pack) don't show OS Build for now - osVersion = std::to_string(outMajor) + "." + std::to_string(outMinor) + "." + std::to_string(outBuild); - } - - std::string configFilename = ""; - const std::wstring configOption = L"--config="; - - std::string controlsConfigFilename = ""; - const std::wstring controlsOption = L"--controlconfig="; - - for (size_t i = 1; i < wideArgs.size(); ++i) { - if (wideArgs[i][0] == L'\0') - continue; - if (wideArgs[i][0] == L'-') { - if (wideArgs[i].find(configOption) != std::wstring::npos && wideArgs[i].size() > configOption.size()) { - const std::wstring tempWide = wideArgs[i].substr(configOption.size()); - configFilename = ConvertWStringToUTF8(tempWide); - } - - if (wideArgs[i].find(controlsOption) != std::wstring::npos && wideArgs[i].size() > controlsOption.size()) { - const std::wstring tempWide = wideArgs[i].substr(controlsOption.size()); - controlsConfigFilename = ConvertWStringToUTF8(tempWide); - } - } + g_osVersionString = std::to_string(outMajor) + "." + std::to_string(outMinor) + "." + std::to_string(outBuild); } // This will be overridden by the actual config. But we do want to log during startup. @@ -1099,69 +1204,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin // Load config up here, because those changes below would be overwritten // if it's not loaded here first. g_Config.SetSearchPath(GetSysDirectory(DIRECTORY_SYSTEM)); - g_Config.Load(configFilename.c_str(), controlsConfigFilename.c_str()); + g_Config.Load(cmdLineOptions.configFilename.c_str(), cmdLineOptions.controlsConfigFilename.c_str()); System_Notify(SystemNotification::CONFIG_LOADED); - bool debugLogLevel = false; - - const std::wstring gpuBackend = L"--graphics="; - - // The rest is handled in NativeInit(). - for (size_t i = 1; i < wideArgs.size(); ++i) { - if (wideArgs[i][0] == L'\0') - continue; - - if (wideArgs[i][0] == L'-') { - switch (wideArgs[i][1]) { - case L'l': - showLog = true; - g_Config.bEnableLogging = true; - break; - case L's': - g_Config.bAutoRun = false; - g_Config.bSaveSettings = false; - break; - case L'd': - debugLogLevel = true; - break; - } - - // NOTE: We need to parse --fullscreen early, before we create the window. - if (!wcscmp(wideArgs[i].c_str(), L"--fullscreen")) { - g_Config.bFullScreen = true; - g_Config.DoNotSaveSetting(&g_Config.bFullScreen); - } else if (!wcscmp(wideArgs[i].c_str(), L"--windowed")) { - g_Config.bFullScreen = false; - g_Config.DoNotSaveSetting(&g_Config.bFullScreen); - } - - if (wideArgs[i].find(gpuBackend) != std::wstring::npos && wideArgs[i].size() > gpuBackend.size()) { - const std::wstring restOfOption = wideArgs[i].substr(gpuBackend.size()); - - // Force software rendering off, as picking gles implies HW acceleration. - // We could add more options for software such as "software-gles", - // "software-vulkan" and "software-d3d11", or something similar. - // For now, software rendering force-activates OpenGL. - if (restOfOption == L"directx11") { - g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11; - g_Config.bSoftwareRendering = false; - } else if (restOfOption == L"gles") { - g_Config.iGPUBackend = (int)GPUBackend::OPENGL; - g_Config.bSoftwareRendering = false; - } else if (restOfOption == L"vulkan") { - g_Config.iGPUBackend = (int)GPUBackend::VULKAN; - g_Config.bSoftwareRendering = false; - } else if (restOfOption == L"software") { - g_Config.iGPUBackend = (int)GPUBackend::OPENGL; - g_Config.bSoftwareRendering = true; - } - } - } - - } -#ifdef _DEBUG - g_Config.bEnableLogging = true; -#endif + // Apply parsed command line options to config. + cmdLineOptions.ApplyToConfig(); #ifndef _DEBUG // See #11719 - too many Vulkan drivers crash on basic init. @@ -1170,18 +1217,12 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } #endif - if (iCmdShow == SW_MAXIMIZE) { - // Consider this to mean --fullscreen. - g_Config.bFullScreen = true; - g_Config.DoNotSaveSetting(&g_Config.bFullScreen); - } - // Consider at least the following cases before changing this code: // - By default in Release, the console should be hidden by default even if logging is enabled. // - By default in Debug, the console should be shown by default. // - The -l switch is expected to show the log console, REGARDLESS of config settings. // - It should be possible to log to a file without showing the console. - g_logManager.GetConsoleListener()->Init(showLog, 150, 120); + g_logManager.GetConsoleListener()->Init(cmdLineOptions.showLogWindow, 150, 120); // Move the console into position. const HWND console = GetConsoleWindow(); @@ -1189,11 +1230,11 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin SetWindowPos(console, NULL, g_Config.iConsoleWindowX, g_Config.iConsoleWindowY, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } - if (debugLogLevel) { + if (cmdLineOptions.debugLogLevel) { g_logManager.SetAllLogLevels(LogLevel::LDEBUG); } - // Media foundation + // Windows Media Foundation - used for camera and (currently, but not later) microphone support (we'll move to WASAPI for audio input later) if (!RegisterCMPTMFApis()) { ERROR_LOG(Log::System, "Failed to load Media Foundation functions"); // Let's unregister again. @@ -1215,8 +1256,7 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin #endif if (g_Config.bShowDebuggerOnLoad) { - MainWindow::CreateDisasmWindow(); - disasmWindow->Show(g_Config.bShowDebuggerOnLoad, false); + PostMessage(hwndMain, MainWindow::WM_USER_SHOW_DISASM, 0, 0); } const bool minimized = iCmdShow == SW_MINIMIZE || iCmdShow == SW_SHOWMINIMIZED || iCmdShow == SW_SHOWMINNOACTIVE; @@ -1225,19 +1265,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin } // Emu thread (and render thread, if any) is always running! - // Only OpenGL uses an externally managed render thread (due to GL's single-threaded context design). Vulkan - // manages its own render thread. - - // We convert command line arguments to UTF-8. - std::vector argsUTF8; - for (const auto &string : wideArgs) { - argsUTF8.push_back(ConvertWStringToUTF8(string)); - } - std::vector args; - for (const auto &string : argsUTF8) { - args.push_back(string.c_str()); - } - + // OpenGL uses an externally managed render thread (due to GL's single-threaded context design). + // Vulkan manages its own render thread. Our D3D backend doesn't have a render thread. + // The Emu thread calls NativeInit() and NativeMain() etc. MainThread_Start((int)args.size(), args.data()); g_InputManager.BeginPolling(); @@ -1252,8 +1282,9 @@ int WINAPI WinMain(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR szCmdLin MainWindow::UpdateCommands(); //hack to make it possible to get to main window from floating windows with Esc - if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE) + if (msg.hwnd != hwndMain && msg.wParam == VK_ESCAPE) { BringWindowToTop(hwndMain); + } } // Translate accelerators and dialog messages... diff --git a/headless/Headless.cpp b/headless/Headless.cpp index a70910d47a..500b116cbb 100644 --- a/headless/Headless.cpp +++ b/headless/Headless.cpp @@ -415,7 +415,7 @@ int main(int argc, const char* argv[]) // There used to be a separate "null" rendering core - just use software. else if (!strcasecmp(gpuName, "software") || !strcasecmp(gpuName, "null")) gpuCore = GPUCORE_SOFTWARE; - else if (!strcasecmp(gpuName, "directx11")) + else if (!strcasecmp(gpuName, "directx11") || !strcasecmp(gpuName, "d3d11")) gpuCore = GPUCORE_DIRECTX11; else if (!strcasecmp(gpuName, "vulkan")) gpuCore = GPUCORE_VULKAN;