From 66f488a17fa3bcefd7c37a8c730148d00fdc54de Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 20 Oct 2026 21:34:45 +0200 Subject: [PATCH] main: take boolean emulator options as value-less flags --- .vscode/launch.json | 2 +- src/launcher/src/mainDialog.cpp | 57 ++++----- src/main.cpp | 198 ++++++++------------------------ 3 files changed, 73 insertions(+), 184 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index 558355cf5..10fee1721 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,7 +27,7 @@ "args": [ "--game", "D:/gamesps5/PPSA07429", "--printf-direction", "File", - "--graphics-debug-dump", "True" + "--graphics-debug-dump" ], "stopAtEntry": false, "cwd": "${workspaceFolder}\\_Build\\vscode-clang", diff --git a/src/launcher/src/mainDialog.cpp b/src/launcher/src/mainDialog.cpp index 2abd30f0b..710929128 100644 --- a/src/launcher/src/mainDialog.cpp +++ b/src/launcher/src/mainDialog.cpp @@ -244,8 +244,10 @@ void MainDialogPrivate::FindInterpreter() { } } -static QString BoolArg(bool value) { - return value ? QStringLiteral("true") : QStringLiteral("false"); +static void AddFlag(QStringList& args, bool enabled, const char* name) { + if (enabled) { + args << name; + } } static QStringList CreateEmulatorArgs(const Configuration& info) { @@ -273,54 +275,37 @@ static QStringList CreateEmulatorArgs(const Configuration& info) { if (info.gpu_index >= 0) { args << "--gpu" << QString::number(info.gpu_index); } - if (info.fullscreen_enabled) { - args << "--fullscreen"; - } - if (info.hdr_enabled) { - args << "--hdr"; - } - if (info.hide_cursor_enabled) { - args << "--hide-cursor"; - } - args << "--readback-linear-images" << BoolArg(info.readback_linear_images); - args << "--sync-raw-image-buffers" << BoolArg(info.sync_raw_image_buffers); - args << "--trophy-notifications" << BoolArg(info.trophy_enabled); + AddFlag(args, info.fullscreen_enabled, "--fullscreen"); + AddFlag(args, info.hdr_enabled, "--hdr"); + AddFlag(args, info.hide_cursor_enabled, "--hide-cursor"); + AddFlag(args, info.readback_linear_images, "--readback-linear-images"); + AddFlag(args, info.sync_raw_image_buffers, "--sync-raw-image-buffers"); + AddFlag(args, !info.trophy_enabled, "--no-trophy-notifications"); args << "--trophy-duration" << QString::number(info.trophy_duration_seconds); - args << "--perf-overlay" << BoolArg(info.perf_overlay_enabled); - args << "--skip-notice-screen" << BoolArg(info.skip_notice_screen); - args << "--network-connected" << BoolArg(info.network_connected); - if (info.tessellation_enabled) { - args << "--tessellation"; - } + AddFlag(args, info.perf_overlay_enabled, "--perf-overlay"); + AddFlag(args, info.skip_notice_screen, "--skip-notice-screen"); + AddFlag(args, info.network_connected, "--network-connected"); + AddFlag(args, info.tessellation_enabled, "--tessellation"); args << "--vblank-frequency" << QString::number(info.vblank_frequency); args << "--console-language" << QString::number(info.console_language); - args << "--vulkan-validation" << BoolArg(info.vulkan_validation_enabled); - args << "--shader-validation" << BoolArg(info.shader_validation_enabled); + AddFlag(args, info.vulkan_validation_enabled, "--vulkan-validation"); + AddFlag(args, info.shader_validation_enabled, "--shader-validation"); args << "--shader-optimization-type" << EnumToText(info.shader_optimization_type); args << "--shader-log-direction" << EnumToText(info.shader_log_direction); args << "--shader-log-folder" << info.shader_log_folder; - args << "--command-buffer-dump" << BoolArg(info.command_buffer_dump_enabled); + AddFlag(args, info.command_buffer_dump_enabled, "--command-buffer-dump"); args << "--command-buffer-dump-folder" << info.command_buffer_dump_folder; args << "--printf-direction" << EnumToText(info.printf_direction); args << "--printf-output-file" << info.printf_output_file; - if (info.profiler_enabled) { - args << "--profile"; - } - args << "--spirv-debug-printf" << "false"; - if (info.amd_cpu_enabled) { - args << "--amd-cpu"; - } + AddFlag(args, info.profiler_enabled, "--profile"); + AddFlag(args, info.amd_cpu_enabled, "--amd-cpu"); #if defined(_WIN32) - if (info.red_zone_protection_enabled) { - args << "--redzone"; - } + AddFlag(args, info.red_zone_protection_enabled, "--redzone"); #endif for (const auto& binding: info.host_input_mapping) { args << "--keymap" << binding; } - if (info.renderdoc_enabled) { - args << "--rd"; - } + AddFlag(args, info.renderdoc_enabled, "--rd"); QString game = info.basedir; if (!info.elf.isEmpty() && !GameContent::IsArchive(info.basedir)) { diff --git a/src/main.cpp b/src/main.cpp index fec8b2cfb..7ebd62517 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "emulator.h" #include "kytyGitVersion.h" +#include #include #include #include @@ -71,35 +72,30 @@ static void PrintUsage() { ::printf(" --amd-cpu Apply AMD CPU instruction patches.\n"); ::printf(" --vblank-frequency Virtual vblank frequency. Default: 60.\n"); ::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n"); - ::printf(" --vulkan-validation Enable Vulkan validation.\n"); - ::printf(" --network-connected Use the host local network (default: false).\n"); - ::printf(" --gpu-assisted-validation Bounds-check shader accesses on the GPU.\n" + ::printf(" --vulkan-validation Enable Vulkan validation.\n"); + ::printf(" --network-connected Use the host local network.\n"); + ::printf(" --gpu-assisted-validation Bounds-check shader accesses on the GPU.\n" " Implies --vulkan-validation; very slow.\n"); - ::printf(" --shader-validation Enable shader validation.\n"); + ::printf(" --shader-validation Enable shader validation.\n"); ::printf(" --tessellation Draw tessellation patches; skipped by default.\n"); ::printf(" --shader-optimization-type None, Size, or Performance.\n"); ::printf(" --shader-log-direction Silent, Console, or File.\n"); ::printf(" --shader-log-folder Shader log output folder.\n"); - ::printf(" --command-buffer-dump Enable command buffer dumps.\n"); + ::printf(" --command-buffer-dump Enable command buffer dumps.\n"); ::printf(" --command-buffer-dump-folder Command buffer dump folder.\n"); - ::printf(" --graphics-debug-dump Enable graphics debug dumps.\n"); + ::printf(" --graphics-debug-dump Enable graphics debug dumps.\n"); ::printf(" --printf-direction Silent, Console, or File.\n"); ::printf(" --printf-output-file Guest printf output file.\n"); ::printf(" --profile Enable the Tracy profiler.\n"); - ::printf(" --spirv-debug-printf Enable SPIR-V debug printf.\n"); - ::printf( - " --readback-linear-images Read back writable linear images on submit.\n"); - ::printf( - " --sync-raw-image-buffers Synchronize raw reads of GPU images. Default: false.\n"); - ::printf( - " --trophy-notifications Show trophy unlock toasts and play their sound.\n"); + ::printf(" --spirv-debug-printf Enable SPIR-V debug printf.\n"); + ::printf(" --readback-linear-images Read back writable linear images on submit.\n"); + ::printf(" --sync-raw-image-buffers Synchronize raw reads of GPU images.\n"); + ::printf(" --no-trophy-notifications Disable trophy unlock toasts and their sound.\n"); ::printf( " --trophy-duration Trophy toast duration, 5-10. Default: 6.\n"); - ::printf(" --perf-overlay Show the performance panel (F2 or Cmd+P).\n"); + ::printf(" --perf-overlay Show the performance panel (F2 or Cmd+P).\n"); ::printf(" --playgo-hack Use the supplied PlayGo stub fallback.\n"); - ::printf( - " --skip-notice-screen Skip startup logos and notices in supported games.\n" - " Default: false.\n"); + ::printf(" --skip-notice-screen Skip startup logos and notices in supported games.\n"); #if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS ::printf(" --redzone Protect the guest SysV red zone.\n"); #endif @@ -117,22 +113,6 @@ static bool NextArg(int argc, char* argv[], int& index, std::string& out) { return true; } -static bool ParseBool(const std::string& value, bool& out) { - if (Common::EqualNoCase(value, "true") || value == "1" || Common::EqualNoCase(value, "yes") || - Common::EqualNoCase(value, "on")) { - out = true; - return true; - } - - if (Common::EqualNoCase(value, "false") || value == "0" || Common::EqualNoCase(value, "no") || - Common::EqualNoCase(value, "off")) { - out = false; - return true; - } - - return false; -} - template static bool ParseEnum(const std::string& value, E& out) { auto enum_value = magic_enum::enum_cast(value.c_str()); @@ -200,6 +180,42 @@ static bool ParseUserId(const std::string& value, int32_t& out) { return true; } +using Config::ConfigOptions; + +struct Flag { + std::string_view name; + bool ConfigOptions::* field; + bool value = true; +}; + +static constexpr Flag FLAGS[] = { + {"--rd", &ConfigOptions::renderdoc_enabled}, + {"--fullscreen", &ConfigOptions::fullscreen_enabled}, + {"--hdr", &ConfigOptions::hdr_enabled}, + {"--hide-cursor", &ConfigOptions::hide_cursor_enabled}, + {"--no-splash", &ConfigOptions::splash_enabled, false}, + {"--vr", &ConfigOptions::vr_enabled}, + {"--amd-cpu", &ConfigOptions::amd_cpu_enabled}, + {"--network-connected", &ConfigOptions::network_connected}, + {"--vulkan-validation", &ConfigOptions::vulkan_validation_enabled}, + {"--gpu-assisted-validation", &ConfigOptions::gpu_assisted_validation_enabled}, + {"--shader-validation", &ConfigOptions::shader_validation_enabled}, + {"--tessellation", &ConfigOptions::tessellation_enabled}, + {"--command-buffer-dump", &ConfigOptions::command_buffer_dump_enabled}, + {"--graphics-debug-dump", &ConfigOptions::graphics_debug_dump_enabled}, + {"--profile", &ConfigOptions::profiler_enabled}, + {"--spirv-debug-printf", &ConfigOptions::spirv_debug_printf_enabled}, + {"--readback-linear-images", &ConfigOptions::readback_linear_images}, + {"--sync-raw-image-buffers", &ConfigOptions::sync_raw_image_buffers}, + {"--no-trophy-notifications", &ConfigOptions::trophy_enabled, false}, + {"--perf-overlay", &ConfigOptions::perf_overlay_enabled}, + {"--playgo-hack", &ConfigOptions::playgo_hack_enabled}, + {"--skip-notice-screen", &ConfigOptions::skip_notice_screen}, +#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS + {"--redzone", &ConfigOptions::red_zone_protection_enabled}, +#endif +}; + static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_help) { show_help = false; @@ -212,63 +228,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he continue; } - if (arg == "--rd") { - options.config.renderdoc_enabled = true; + if (const auto* flag = std::ranges::find(FLAGS, arg, &Flag::name); flag != std::end(FLAGS)) { + options.config.*flag->field = flag->value; continue; } - if (arg == "--fullscreen") { - options.config.fullscreen_enabled = true; - continue; - } - - if (arg == "--hdr") { - options.config.hdr_enabled = true; - continue; - } - - if (arg == "--hide-cursor") { - options.config.hide_cursor_enabled = true; - continue; - } - - if (arg == "--no-splash") { - options.config.splash_enabled = false; - continue; - } - - if (arg == "--vr") { - options.config.vr_enabled = true; - continue; - } - - if (arg == "--amd-cpu") { - options.config.amd_cpu_enabled = true; - continue; - } - - if (arg == "--playgo-hack") { - options.config.playgo_hack_enabled = true; - continue; - } - - if (arg == "--tessellation") { - options.config.tessellation_enabled = true; - continue; - } - - if (arg == "--profile") { - options.config.profiler_enabled = true; - continue; - } - -#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS - if (arg == "--redzone") { - options.config.red_zone_protection_enabled = true; - continue; - } -#endif - if (!arg.starts_with("--")) { ::printf("game input must be provided with --game\n"); return false; @@ -411,26 +375,6 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he ::printf("invalid console language: %s\n", value.c_str()); return false; } - } else if (arg == "--network-connected") { - if (!ParseBool(value, options.config.network_connected)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--vulkan-validation") { - if (!ParseBool(value, options.config.vulkan_validation_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--gpu-assisted-validation") { - if (!ParseBool(value, options.config.gpu_assisted_validation_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--shader-validation") { - if (!ParseBool(value, options.config.shader_validation_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } } else if (arg == "--shader-optimization-type") { if (!ParseEnum(value, options.config.shader_optimization_type)) { ::printf("invalid shader optimization type: %s\n", value.c_str()); @@ -443,18 +387,8 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he } } else if (arg == "--shader-log-folder") { options.config.shader_log_folder = Common::PathFromUtf8(value); - } else if (arg == "--command-buffer-dump") { - if (!ParseBool(value, options.config.command_buffer_dump_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } } else if (arg == "--command-buffer-dump-folder") { options.config.command_buffer_dump_folder = Common::PathFromUtf8(value); - } else if (arg == "--graphics-debug-dump") { - if (!ParseBool(value, options.config.graphics_debug_dump_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } } else if (arg == "--printf-direction") { if (!ParseEnum(value, options.config.printf_direction)) { ::printf("invalid printf direction: %s\n", value.c_str()); @@ -462,36 +396,6 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he } } else if (arg == "--printf-output-file") { options.config.printf_output_file = Common::PathFromUtf8(value); - } else if (arg == "--spirv-debug-printf") { - if (!ParseBool(value, options.config.spirv_debug_printf_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--readback-linear-images") { - if (!ParseBool(value, options.config.readback_linear_images)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--sync-raw-image-buffers") { - if (!ParseBool(value, options.config.sync_raw_image_buffers)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--trophy-notifications") { - if (!ParseBool(value, options.config.trophy_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--skip-notice-screen") { - if (!ParseBool(value, options.config.skip_notice_screen)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } - } else if (arg == "--perf-overlay") { - if (!ParseBool(value, options.config.perf_overlay_enabled)) { - ::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str()); - return false; - } } else if (arg == "--keymap") { const auto split = value.find('='); if (split == std::string::npos || split == 0 || split + 1 == value.size()) {