diff --git a/docs/user/CommandLine.md b/docs/user/CommandLine.md index b8d71ac61f..a63a41a27c 100644 --- a/docs/user/CommandLine.md +++ b/docs/user/CommandLine.md @@ -1,32 +1,44 @@ # User Handbook - Command Line -There are two main applications, an SDL-based app (`eden-cli`) and a Qt based app (`eden`); both accept command line arguments. - -## eden +There are two main applications, an SDL-based app (`eden-cli`) and a Qt based app (`eden`); both accept the same command line arguments. - `./eden `: Running with a single argument and nothing else, will make the emulator look for the given file and load it, this behavior is similar to `eden-cli`; allows dragging and dropping games into the application. -- `-g `: Alternate way to specify what to load, overrides. However let it be noted that arguments that use `-` will be treated as options/ignored, if your game, for some reason, starts with `-`, in order to safely handle it you may need to specify it as an argument. -- `-f`: Use fullscreen. -- `-u `: Select the index of the user to load as. -- `-input-profile `: Specifies input profile name to use (for player #0 only). +- `--debug/-d`: Enter debug mode, allow gdb stub at port `1234` +- `--config/-c`: Specify alternate configuration file. +- `--fullscreen/-f`: Use fullscreen. +- `--help/-h`: Display help. +- `--game/-g `: Alternate way to specify what to load, overrides. However let it be noted that arguments that use `-` will be treated as options/ignored, if your game, for some reason, starts with `-`, in order to safely handle it you may need to specify it as an argument. +- `--multiplayer/-m`: Specify multiplayer options. +- `--program/-p`: Specify the program arguments to pass (optional). +- `--user/-u `: Specify the user index. +- `--version/-v`: Display version and quit. +- `--input-profile/-i `: Specifies input profile name to use (for player #0 only). +- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings. +- `--filter/-x`: Sets the debug log filter irrespective of settings. +- `--singlecore/-s`: Forces single-core regardless of settings. + +Only the Qt frontend supports the following arguments: + - `-qlaunch`: Launch QLaunch. - `-hlaunch`: Launch homebrew launcher `nx-hbloader`. - Requires a copy of Atmosphere to be extracted onto `sdmc`. - This is a shorthand for `/sdmc/atmosphere/hbl.nsp`. - `-setup`: Launch setup applet. -## eden-cli +`eden` (provided with `--room`), and `eden-room` supports the following options as well: -- `--debug/-d`: Enter debug mode, allow gdb stub at port `1234` -- `--config/-c`: Specify alternate configuration file. -- `--fullscreen/-f`: Set fullscreen. -- `--help/-h`: Display help. -- `--game/-g`: Specify the game to run. -- `--multiplayer/-m`: Specify multiplayer options. -- `--program/-p`: Specify the program arguments to pass (optional). -- `--user/-u`: Specify the user index. -- `--version/-v`: Display version and quit. -- `--input-profile/-i`: Specifies input profile name to use (for player #0 only). -- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings. -- `--filter/-x`: Sets the debug log filter irrespective of settings. -- `--singlecore/-s`: Forces single-core regardless of settings. +- `-n/--room-name`: The name of the room. +- `-d/--room-description`: The room description. +- `-s/--bind-address`: The bind address for the room. +- `-p/--port`: The port used for the room. +- `-m/--max-members`: The maximum number of players for this room. +- `-w/--password`: The password for the room. +- `-g/--preferred-game`: The preferred game for this room. +- `-i/--preferred-game-id`: The preferred game-id for this room. +- `-u/--username`: The username used for announce. +- `-t/--token`: The token used for announce. +- `-a/--web-api-url`: yuzu Web API url. +- `-b/--ban-list-file`: The file for storing the room ban list. +- `-l/--log-file`: The file for storing the room log. +- `-h/--help`: Display this help and exit. +- `-v/--version`: Output version information and exit. diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 508ace3501..2b12ebeca7 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -23,6 +23,8 @@ add_library(core STATIC core_timing.h cpu_manager.cpp cpu_manager.h + launch_params.cpp + launch_params.h crypto/aes_util.cpp crypto/aes_util.h crypto/ctr_encryption_layer.cpp @@ -1201,6 +1203,9 @@ endif() target_include_directories(core PRIVATE ${OPUS_INCLUDE_DIRS}) target_link_libraries(core PUBLIC common PRIVATE audio_core hid_core network video_core nx_tzdb tz) +if (MSVC) + target_link_libraries(core PRIVATE getopt) +endif() if (BOOST_NO_HEADERS) target_link_libraries(core PUBLIC Boost::container Boost::heap Boost::asio Boost::process Boost::crc) diff --git a/src/core/launch_params.cpp b/src/core/launch_params.cpp new file mode 100644 index 0000000000..3230c4df42 --- /dev/null +++ b/src/core/launch_params.cpp @@ -0,0 +1,205 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include +#include + +#include "common/assert.h" +#include "common/logging.h" +#include "common/settings.h" +#include "common/string_util.h" +#include "common/scm_rev.h" +#include "core/core.h" +#include "core/hle/service/acc/profile_manager.h" +#include "core/launch_params.h" + +#undef _UNICODE +#include +#ifndef _MSC_VER +#include +#endif + +namespace Core { +LaunchParams ParseLaunchParams(Core::System& system, int argc, char *argv[], wchar_t *argv_w[]) noexcept { + LaunchParams p{}; + + int option_index = 0; + static struct option long_options[] = { + // clang-format off + {"debug", no_argument, 0, 'd'}, + {"config", required_argument, 0, 'c'}, + {"fullscreen", no_argument, 0, 'f'}, + {"help", no_argument, 0, 'h'}, + {"game", required_argument, 0, 'g'}, + {"multiplayer", required_argument, 0, 'm'}, + {"program", optional_argument, 0, 'p'}, + {"user", required_argument, 0, 'u'}, + {"version", no_argument, 0, 'v'}, + {"input-profile", no_argument, 0, 'i'}, + {"null-render", no_argument, 0, 'n'}, + {"singlecore", no_argument, 0, 's'}, + {"filter", no_argument, 0, 'x'}, + {0, 0, 0, 0}, + // clang-format on + }; + + while (optind < argc) { + if (int arg = getopt_long(argc, argv, "dc:fhg:m:p:u:vinsx", long_options, &option_index); arg != -1) { + switch (char(arg)) { + case 'd': + p.override_gdb_port = uint16_t(atoi(optarg)); + break; + case 'c': + p.config_path = optarg; + break; + case 'f': + p.fullscreen = true; + LOG_INFO(Frontend, "Starting in fullscreen mode..."); + break; + case 'h': + p.print_help = true; + break; + case 'g': + p.filepath = std::string(optarg); + break; + case 'i': { + p.input_profile = std::string(optarg); + break; + } + case 'm': { + p.use_multiplayer = true; + const std::string str_arg(optarg); + // regex to check if the format is nickname:password@ip:port + // with optional :password + const std::regex re("^([^:]+)(?::(.+))?@([^:]+)(?::([0-9]+))?$"); + if (std::regex_match(str_arg, re)) { + std::smatch match; + std::regex_search(str_arg, match, re); + ASSERT(match.size() == 5); + p.nickname = match[1]; + p.password = match[2]; + p.address = match[3]; + if (!match[4].str().empty()) { + p.port = u16(std::strtoul(match[4].str().c_str(), nullptr, 0)); + } + std::regex nickname_re("^[a-zA-Z0-9._\\- ]+$"); + ASSERT(std::regex_match(p.nickname, nickname_re) && "Nickname is not valid. Must be 4 to 20 alphanumeric characters"); + ASSERT(!p.address.empty() && "Address is empty"); + } + break; + } + case 'p': + p.program_args = argv[optind]; + ++optind; + break; + case 'u': { + // Launch game with a specific user + bool argument_ok = isdigit(optarg[0]); + p.selected_user = atoi(optarg); + if (!argument_ok) { + // try to look it up by username, only finds the first username that matches. + auto const user_idx = system.GetProfileManager().GetUserIndex(optarg); + if (user_idx != std::nullopt) { + p.selected_user = user_idx.value(); + } else { + LOG_ERROR(Frontend, "Invalid user argument '{}'", optarg); + break; + } + } + if (system.GetProfileManager().UserExistsIndex(*p.selected_user)) { + Settings::values.current_user = s32(*p.selected_user); + } else { + LOG_ERROR(Frontend, "Selected user {} doesn't exist", p.selected_user); + } + break; + } + case 'v': + p.print_version = true; + break; + case 'n': + p.force_null_render = true; + break; + case 's': + p.force_single_core = true; + break; + case 'x': + p.log_filter = argv[optind]; + ++optind; + break; + } + } else { + // only kept due to shortcuts made by Qt frontend which use "-qlaunch" + if (strcmp(argv[optind], "-hlaunch") == 0) { + p.launch_hlaunch = true; + } else if (strcmp(argv[optind], "-qlaunch") == 0) { + p.launch_qlaunch = true; + } else if (strcmp(argv[optind], "-setup") == 0) { + p.launch_setup = true; + } else { + // qt feeds utf8 data, sdl frontend feeds raw utf16 data +#ifdef _WIN32 + p.filepath = argv_w != nullptr + ? Common::UTF16ToUTF8(argv_w[optind]) + : argv[optind]; +#else + p.filepath = argv[optind]; +#endif + } + optind++; + } + } + p.argv0 = argv[0]; + return p; +} + +void ApplyLaunchParams(LaunchParams const& lp) noexcept { + // apply the log_filter setting + // the logger was initialized before and doesn't pick up the filter on its own + Common::Log::Filter filter{}; + filter.ParseFilterString(lp.log_filter.value_or(Settings::values.log_filter.GetValue())); + Common::Log::SetGlobalFilter(filter); + + if (!lp.program_args.empty()) { + Settings::values.program_args = lp.program_args; + } + if (!lp.input_profile.empty()) { + auto& players = Settings::values.players.GetValue(); + players[0].profile_name = lp.input_profile; + } + if (lp.selected_user.has_value()) { + Settings::values.current_user = std::clamp(*lp.selected_user, 0, 7); + } + if (lp.override_gdb_port.has_value()) { + Settings::values.use_gdbstub = true; + Settings::values.gdbstub_port = *lp.override_gdb_port; + } + if (lp.force_single_core) { + Settings::values.use_multi_core = false; + } + if (lp.force_null_render) { + Settings::values.renderer_backend = Settings::RendererBackend::Null; + } + + if (lp.print_version) { + LOG_INFO(Frontend, "Eden {} {}", Common::g_scm_branch, Common::g_scm_desc); + } + if (lp.print_help) { + LOG_INFO(Frontend, + "Usage: {}" + " [options] \n" + "-c, --config Load the specified configuration file\n" + "-f, --fullscreen Start in fullscreen mode\n" + "-g, --game File path of the game to load\n" + "-h, --help Display this help and exit\n" + "-m, --multiplayer=nick:password@address:port" + " Nickname, password, address and port for multiplayer\n" + "-p, --program Pass following string as arguments to executable\n" + "-u, --user Select a specific user profile from 0 to 7\n" + "-d, --debug Run the GDB stub on a port from 1 to 65535\n" + "-v, --version Output version information and exit\n", + lp.argv0 + ); + } +} + +} diff --git a/src/core/launch_params.h b/src/core/launch_params.h new file mode 100644 index 0000000000..4da30fc1c2 --- /dev/null +++ b/src/core/launch_params.h @@ -0,0 +1,43 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include +#include +#include "common/common_types.h" +#include "network/room.h" + +namespace Core { + +class System; +struct LaunchParams { + std::string argv0{}; + std::string filepath{}; + std::string nickname{}; + std::string password{}; + std::string address{}; + std::string input_profile{}; + std::string program_args{}; + std::optional config_path{}; + std::optional selected_user{}; + std::optional override_gdb_port{}; + std::optional log_filter{}; + u16 port = Network::DefaultRoomPort; + bool use_multiplayer = false; + bool fullscreen = false; + bool force_null_render = false; + bool force_single_core = false; + // print + bool print_version = false; + bool print_help = false; + // qt + bool launch_hlaunch = false; + bool launch_qlaunch = false; + bool launch_setup = false; +}; + +LaunchParams ParseLaunchParams(Core::System& system, int argc, char *argv[], wchar_t *argv_w[]) noexcept; +void ApplyLaunchParams(LaunchParams const& lp) noexcept; + +} diff --git a/src/yuzu/main_window.cpp b/src/yuzu/main_window.cpp index 95b91a4f38..ce9fb75000 100644 --- a/src/yuzu/main_window.cpp +++ b/src/yuzu/main_window.cpp @@ -3,6 +3,7 @@ // Static Qt on macOS doesn't use Vulkan // Other platforms do, and thus have conflicting VulkanMemoryAllocator symbols +#include "core/launch_params.h" #if defined(QT_STATICPLUGIN) && !defined(__APPLE__) #undef VMA_IMPLEMENTATION #endif @@ -514,79 +515,28 @@ MainWindow::MainWindow(bool has_broken_vulkan) // to prevent the UI from blowing up. UpdateUITheme(); - QStringList args = QApplication::arguments(); + if (QStringList args = QApplication::arguments(); args.size() >= 2) { + QList qba{}; + for (auto const& e : args) + qba.push_back(e.toUtf8()); + std::vector args_cstr{}; + for (auto& e : qba) + args_cstr.push_back(e.data()); - if (args.size() < 2) { - return; - } + auto const lp = Core::ParseLaunchParams(*QtCommon::system, args_cstr.size(), args_cstr.data(), nullptr); - QString game_path; - bool should_launch_qlaunch = false; - bool should_launch_hlaunch = false; - bool should_launch_setup = false; - bool has_gamepath = false; - bool is_fullscreen = false; - - // Preserves drag/drop functionality - for (int i = 1; i < args.size(); ++i) { - if (args[i] == QStringLiteral("-f")) { - // Launch game in fullscreen mode - is_fullscreen = true; - } else if (args[i] == QStringLiteral("-u") && i < args.size() - 1) { - // Launch game with a specific user - int user_arg_idx = ++i; - bool argument_ok; - std::size_t selected_user = args[user_arg_idx].toUInt(&argument_ok); - if (!argument_ok) { - // try to look it up by username, only finds the first username that matches. - std::string const user_arg_str = args[user_arg_idx].toStdString(); - auto const user_idx = - QtCommon::system->GetProfileManager().GetUserIndex(user_arg_str); - if (user_idx != std::nullopt) { - selected_user = user_idx.value(); - } else { - LOG_ERROR(Frontend, "Invalid user argument '{}'", user_arg_str); - continue; - } - } - if (QtCommon::system->GetProfileManager().UserExistsIndex(selected_user)) { - Settings::values.current_user = s32(selected_user); - user_flag_cmd_line = true; - } else { - LOG_ERROR(Frontend, "Selected user {} doesn't exist", selected_user); - } - } else if (args[i] == QStringLiteral("-g") && i < args.size() - 1) { - // Launch game at path - game_path = args[++i]; - has_gamepath = true; - } else if (args[i] == QStringLiteral("-input-profile") && i < args.size() - 1) { - auto& players = Settings::values.players.GetValue(); - players[0].profile_name = args[++i].toStdString(); - } else if (args[i] == QStringLiteral("-qlaunch")) { - should_launch_qlaunch = true; - } else if (args[i] == QStringLiteral("-hlaunch")) { - should_launch_hlaunch = true; - } else if (args[i] == QStringLiteral("-setup")) { - should_launch_setup = true; - } else { - game_path = args[i]; - has_gamepath = true; + // Override fullscreen setting if gamepath or argument is provided + if (!lp.filepath.empty() || lp.fullscreen) { + ui->action_Fullscreen->setChecked(lp.fullscreen); } - } - // Override fullscreen setting if gamepath or argument is provided - if (has_gamepath || is_fullscreen) { - ui->action_Fullscreen->setChecked(is_fullscreen); - } - - if (should_launch_setup) { - LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::Starter), std::nullopt); - } else { - if (!game_path.isEmpty()) { - BootGame(game_path, ApplicationAppletParameters()); - } else if (should_launch_qlaunch) { + if (!lp.filepath.empty()) { + BootGame(QString::fromStdString(lp.filepath), ApplicationAppletParameters()); + } else if (lp.launch_setup) { + LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::Starter), std::nullopt); + } else if (lp.launch_qlaunch) { LaunchFirmwareApplet(u64(Service::AM::AppletProgramId::QLaunch), std::nullopt); - } else if (should_launch_hlaunch) { + } else if (lp.launch_hlaunch) { std::filesystem::path const sd_dir = Common::FS::GetEdenPathString(Common::FS::EdenPath::SDMCDir); auto const hbl_path = (sd_dir / "atmosphere" / "hbl.nsp").string(); diff --git a/src/yuzu_cmd/CMakeLists.txt b/src/yuzu_cmd/CMakeLists.txt index 09a9bd6da1..17a1545167 100644 --- a/src/yuzu_cmd/CMakeLists.txt +++ b/src/yuzu_cmd/CMakeLists.txt @@ -42,9 +42,6 @@ target_link_libraries(yuzu-cmd PRIVATE common core input_common frontend_common if (ENABLE_OPENGL) target_link_libraries(yuzu-cmd PRIVATE glad) endif() -if (MSVC) - target_link_libraries(yuzu-cmd PRIVATE getopt) -endif() target_link_libraries(yuzu-cmd PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads) create_resource("../../dist/eden.bmp" "yuzu_cmd/yuzu_icon.h" "yuzu_icon") diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index a161418289..e72cb81d37 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -10,6 +10,7 @@ #include #include #include "common/settings_enums.h" +#include "core/launch_params.h" #ifdef __EMSCRIPTEN__ #include #endif @@ -52,12 +53,6 @@ #include "common/windows/timer_resolution.h" #endif -#undef _UNICODE -#include -#ifndef _MSC_VER -#include -#endif - #ifdef _WIN32 extern "C" { // tells Nvidia and AMD drivers to use the dedicated GPU by default on laptops with switchable @@ -67,25 +62,6 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #endif -static void PrintHelp(const char* argv0) { - std::cout << "Usage: " << argv0 - << " [options] \n" - "-c, --config Load the specified configuration file\n" - "-f, --fullscreen Start in fullscreen mode\n" - "-g, --game File path of the game to load\n" - "-h, --help Display this help and exit\n" - "-m, --multiplayer=nick:password@address:port" - " Nickname, password, address and port for multiplayer\n" - "-p, --program Pass following string as arguments to executable\n" - "-u, --user Select a specific user profile from 0 to 7\n" - "-d, --debug Run the GDB stub on a port from 1 to 65535\n" - "-v, --version Output version information and exit\n"; -} - -static void PrintVersion() { - std::cout << "Eden " << Common::g_scm_branch << " " << Common::g_scm_desc << std::endl; -} - static void OnStateChanged(const Network::RoomMember::State& state) { switch (state) { case Network::RoomMember::State::Idle: @@ -208,168 +184,18 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { LOG_CRITICAL(Frontend, "Failed to get command line arguments"); return SDL_APP_FAILURE; } -#endif - std::string filepath; - std::optional config_path{}; - std::string program_args; - std::optional selected_user{}; - std::optional override_gdb_port{}; - bool use_multiplayer = false; - bool fullscreen = false; - bool force_null_render = false; - bool force_single_core = false; - std::string nickname{}; - std::string password{}; - std::string address{}; - std::string input_profile{}; - std::optional log_filter{}; - u16 port = Network::DefaultRoomPort; - - static struct option long_options[] = { - // clang-format off - {"debug", no_argument, 0, 'd'}, - {"config", required_argument, 0, 'c'}, - {"fullscreen", no_argument, 0, 'f'}, - {"help", no_argument, 0, 'h'}, - {"game", required_argument, 0, 'g'}, - {"multiplayer", required_argument, 0, 'm'}, - {"program", optional_argument, 0, 'p'}, - {"user", required_argument, 0, 'u'}, - {"version", no_argument, 0, 'v'}, - {"input-profile", no_argument, 0, 'i'}, - {"null-render", no_argument, 0, 'n'}, - {"singlecore", no_argument, 0, 's'}, - {"filter", no_argument, 0, 'x'}, - {0, 0, 0, 0}, - // clang-format on - }; - - while (optind < argc) { - int arg = getopt_long(argc, argv, "g:fhvcip::c:u:d:", long_options, &option_index); - if (arg != -1) { - switch (char(arg)) { - case 'd': - override_gdb_port = uint16_t(atoi(optarg)); - break; - case 'c': - config_path = optarg; - break; - case 'f': - fullscreen = true; - LOG_INFO(Frontend, "Starting in fullscreen mode..."); - break; - case 'h': - PrintHelp(argv[0]); - return SDL_APP_FAILURE; - case 'g': - filepath = std::string(optarg); - break; - case 'i': { - input_profile = std::string(optarg); - break; - } - case 'm': { - use_multiplayer = true; - const std::string str_arg(optarg); - // regex to check if the format is nickname:password@ip:port - // with optional :password - const std::regex re("^([^:]+)(?::(.+))?@([^:]+)(?::([0-9]+))?$"); - if (!std::regex_match(str_arg, re)) { - std::cout << "Wrong format for option --multiplayer\n"; - PrintHelp(argv[0]); - return SDL_APP_FAILURE; - } - - std::smatch match; - std::regex_search(str_arg, match, re); - ASSERT(match.size() == 5); - nickname = match[1]; - password = match[2]; - address = match[3]; - if (!match[4].str().empty()) { - port = u16(std::strtoul(match[4].str().c_str(), nullptr, 0)); - } - std::regex nickname_re("^[a-zA-Z0-9._\\- ]+$"); - if (!std::regex_match(nickname, nickname_re)) { - LOG_ERROR(Frontend, "Nickname is not valid. Must be 4 to 20 alphanumeric characters"); - return SDL_APP_FAILURE; - } - if (address.empty()) { - LOG_ERROR(Frontend, "Address to room must not be empty"); - return SDL_APP_FAILURE; - } - break; - } - case 'p': - program_args = argv[optind]; - ++optind; - break; - case 'u': - selected_user = atoi(optarg); - break; - case 'v': - PrintVersion(); - return SDL_APP_FAILURE; - case 'n': - force_null_render = true; - break; - case 's': - force_single_core = true; - break; - case 'x': - log_filter = argv[optind]; - ++optind; - break; - } - } else { -#ifdef _WIN32 - filepath = Common::UTF16ToUTF8(argv_w[optind]); #else - filepath = argv[optind]; + wchar_t **argv_w = nullptr; #endif - optind++; - } - } - - SdlConfig config{config_path}; - - // apply the log_filter setting - // the logger was initialized before and doesn't pick up the filter on its own - Common::Log::Filter filter; - filter.ParseFilterString(log_filter.value_or(Settings::values.log_filter.GetValue())); - Common::Log::SetGlobalFilter(filter); - - if (!program_args.empty()) { - Settings::values.program_args = program_args; - } - - if (!input_profile.empty()) { - auto& players = Settings::values.players.GetValue(); - players[0].profile_name = input_profile; - } - - if (selected_user.has_value()) { - Settings::values.current_user = std::clamp(*selected_user, 0, 7); - } - - if (override_gdb_port.has_value()) { - Settings::values.use_gdbstub = true; - Settings::values.gdbstub_port = *override_gdb_port; - } - - if (force_single_core) { - Settings::values.use_multi_core = false; - } - - if (force_null_render) { - Settings::values.renderer_backend = Settings::RendererBackend::Null; - } - + Core::LaunchParams lp = Core::ParseLaunchParams(argc, argv, argv_w); #ifdef _WIN32 LocalFree(argv_w); #endif + SdlConfig config{lp.config_path}; - if (filepath.empty()) { + Core::ApplyLaunchParams(lp); + + if (lp.filepath.empty()) { LOG_CRITICAL(Frontend, "Failed to load ROM: No ROM specified"); return SDL_APP_FAILURE; } @@ -386,14 +212,14 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { case Settings::RendererBackend::OpenGL_GLSL: case Settings::RendererBackend::OpenGL_GLASM: case Settings::RendererBackend::OpenGL_SPIRV: - state->emu_window = std::make_unique(&input_subsystem, state->system, fullscreen); + state->emu_window = std::make_unique(&input_subsystem, state->system, lp.fullscreen); break; #endif case Settings::RendererBackend::Vulkan: - state->emu_window = std::make_unique(&input_subsystem, state->system, fullscreen); + state->emu_window = std::make_unique(&input_subsystem, state->system, lp.fullscreen); break; case Settings::RendererBackend::Null: - state->emu_window = std::make_unique(&input_subsystem, state->system, fullscreen); + state->emu_window = std::make_unique(&input_subsystem, state->system, lp.fullscreen); break; default: LOG_CRITICAL(Frontend, "Invalid renderer backend"); @@ -413,12 +239,12 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { Service::AM::FrontendAppletParameters load_parameters{ .applet_id = Service::AM::AppletId::Application, }; - const Core::SystemResultStatus load_result = state->system.Load(*state->emu_window, filepath, load_parameters); + const Core::SystemResultStatus load_result = state->system.Load(*state->emu_window, lp.filepath, load_parameters); switch (load_result) { case Core::SystemResultStatus::Success: break; // Expected case case Core::SystemResultStatus::ErrorGetLoader: - LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", filepath); + LOG_CRITICAL(Frontend, "Failed to obtain loader for {}!", lp.filepath); return SDL_APP_FAILURE; case Core::SystemResultStatus::ErrorLoader: LOG_CRITICAL(Frontend, "Failed to load ROM!"); @@ -440,14 +266,14 @@ extern "C" SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) { return SDL_APP_FAILURE; } - if (use_multiplayer) { + if (lp.use_multiplayer) { if (auto member = Network::GetRoomMember().lock()) { member->BindOnChatMessageReceived(OnMessageReceived); member->BindOnStatusMessageReceived(OnStatusMessageReceived); member->BindOnStateChanged(OnStateChanged); member->BindOnError(OnNetworkError); - LOG_DEBUG(Network, "Start connection to {}:{} with nickname {}", address, port, nickname); - member->Join(nickname, address.c_str(), port, 0, Network::NoPreferredIP, password); + LOG_DEBUG(Network, "Start connection to {}:{} with nickname {}", lp.address, lp.port, lp.nickname); + member->Join(lp.nickname, lp.address.c_str(), lp.port, 0, Network::NoPreferredIP, lp.password); } else { LOG_ERROR(Network, "Could not access RoomMember"); return SDL_APP_FAILURE;