From 29836ea74e74c4eaf8db2ca73a52b10dd6f2ca83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 19 Jul 2026 11:26:13 +0200 Subject: [PATCH] Move the new incomplete command line parser to Core --- CMakeLists.txt | 2 + Core/CmdLine.cpp | 94 +++++++++++++++++++++++ Core/CmdLine.h | 26 +++++++ Core/Core.vcxproj | 2 + Core/Core.vcxproj.filters | 6 ++ UI/NativeApp.cpp | 9 ++- UWP/CoreUWP/CoreUWP.vcxproj | 2 + UWP/CoreUWP/CoreUWP.vcxproj.filters | 2 + Windows/main.cpp | 114 +--------------------------- android/jni/Android.mk | 1 + 10 files changed, 141 insertions(+), 117 deletions(-) create mode 100644 Core/CmdLine.cpp create mode 100644 Core/CmdLine.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 4dfcc74d53..05bb1fafa4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2142,6 +2142,8 @@ endif() add_library(${CoreLibName} ${CoreLinkType} ${CoreExtra} ${CommonJIT} + Core/CmdLine.cpp + Core/CmdLine.h Core/Config.cpp Core/Config.h Core/ConfigSettings.cpp diff --git a/Core/CmdLine.cpp b/Core/CmdLine.cpp new file mode 100644 index 0000000000..532386f099 --- /dev/null +++ b/Core/CmdLine.cpp @@ -0,0 +1,94 @@ +#include "Core/Config.h" +#include "Core/CmdLine.h" +#include "Common/StringUtils.h" + +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; + } +} diff --git a/Core/CmdLine.h b/Core/CmdLine.h new file mode 100644 index 0000000000..f6548738a0 --- /dev/null +++ b/Core/CmdLine.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "Core/ConfigValues.h" + +// We collect command line options in this struct, then we apply it to the config after it's been loaded. +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; +}; diff --git a/Core/Core.vcxproj b/Core/Core.vcxproj index 9a5aef32ec..98d2207a6c 100644 --- a/Core/Core.vcxproj +++ b/Core/Core.vcxproj @@ -437,6 +437,7 @@ + @@ -971,6 +972,7 @@ + diff --git a/Core/Core.vcxproj.filters b/Core/Core.vcxproj.filters index 2cd01b7853..605f34d4b0 100644 --- a/Core/Core.vcxproj.filters +++ b/Core/Core.vcxproj.filters @@ -1390,6 +1390,9 @@ Util + + Core + @@ -2250,6 +2253,9 @@ Util + + Core + diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index eafea2dfe7..6dcb681def 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -619,19 +619,19 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch break; case 'j': g_Config.iCpuCore = (int)CPUCore::JIT; - g_Config.bSaveSettings = false; + g_Config.DoNotSaveSetting(&g_Config.iCpuCore); break; case 'i': g_Config.iCpuCore = (int)CPUCore::INTERPRETER; - g_Config.bSaveSettings = false; + g_Config.DoNotSaveSetting(&g_Config.iCpuCore); break; case 'r': g_Config.iCpuCore = (int)CPUCore::IR_INTERPRETER; - g_Config.bSaveSettings = false; + g_Config.DoNotSaveSetting(&g_Config.iCpuCore); break; case 'J': g_Config.iCpuCore = (int)CPUCore::JIT_IR; - g_Config.bSaveSettings = false; + g_Config.DoNotSaveSetting(&g_Config.iCpuCore); break; case '-': if (!strncmp(argv[i], "--loglevel=", strlen("--loglevel=")) && strlen(argv[i]) > strlen("--loglevel=")) @@ -649,6 +649,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch g_Config.bFullScreen = true; } if (!strncmp(argv[i], "--root=", strlen("--root=")) && strlen(argv[i]) > strlen("--root=")) { + g_Config.DoNotSaveSetting(&g_Config.mountRoot); g_Config.mountRoot = Path(argv[i] + strlen("--root=")); } if (!strcmp(argv[i], "--windowed")) { diff --git a/UWP/CoreUWP/CoreUWP.vcxproj b/UWP/CoreUWP/CoreUWP.vcxproj index dadb1715b2..0110a45f01 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj +++ b/UWP/CoreUWP/CoreUWP.vcxproj @@ -86,6 +86,7 @@ + @@ -359,6 +360,7 @@ + diff --git a/UWP/CoreUWP/CoreUWP.vcxproj.filters b/UWP/CoreUWP/CoreUWP.vcxproj.filters index 211b5a9410..7e96f6ac8f 100644 --- a/UWP/CoreUWP/CoreUWP.vcxproj.filters +++ b/UWP/CoreUWP/CoreUWP.vcxproj.filters @@ -411,6 +411,7 @@ + @@ -684,6 +685,7 @@ + diff --git a/Windows/main.cpp b/Windows/main.cpp index 67abc9f431..b2fc64f2c7 100644 --- a/Windows/main.cpp +++ b/Windows/main.cpp @@ -50,6 +50,7 @@ #include "Core/Config.h" #include "Core/ConfigValues.h" +#include "Core/CmdLine.h" #include "Core/SaveState.h" #include "Core/Instance.h" #include "Core/HLE/Plugins.h" @@ -1022,119 +1023,6 @@ static void WinMainCleanup() { } } -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. diff --git a/android/jni/Android.mk b/android/jni/Android.mk index 7d39f6d392..ff6829ab39 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -608,6 +608,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/Core/ControlMapper.cpp \ $(SRC)/Core/Core.cpp \ $(SRC)/Core/Compatibility.cpp \ + $(SRC)/Core/CmdLine.cpp \ $(SRC)/Core/Config.cpp \ $(SRC)/Core/ConfigSettings.cpp \ $(SRC)/Core/CoreTiming.cpp \