diff --git a/CMakeLists.txt b/CMakeLists.txt index 37021746d..f137a7b39 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,7 @@ string(TIMESTAMP BUILD_DATE "%Y-%m-%d %H:%M:%S") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp.in" "${CMAKE_CURRENT_SOURCE_DIR}/src/common/scm_rev.cpp" @ONLY) -find_package(Boost 1.84.0 CONFIG) +find_package(Boost 1.84.0 CONFIG COMPONENTS program_options) find_package(FFmpeg 5.1.2 MODULE) find_package(fmt 10.2.0 CONFIG) find_package(glslang 14.2.0 CONFIG) @@ -762,7 +762,7 @@ endif() create_target_directory_groups(shadps4) target_link_libraries(shadps4 PRIVATE magic_enum::magic_enum fmt::fmt toml11::toml11 tsl::robin_map xbyak::xbyak Tracy::TracyClient RenderDoc::API FFmpeg::ffmpeg Dear_ImGui gcn) -target_link_libraries(shadps4 PRIVATE Boost::headers GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml) +target_link_libraries(shadps4 PRIVATE Boost::headers Boost::program_options GPUOpen::VulkanMemoryAllocator sirit Vulkan::Headers xxHash::xxhash Zydis::Zydis glslang::SPIRV glslang::glslang SDL3::SDL3 pugixml::pugixml) target_compile_definitions(shadps4 PRIVATE IMGUI_USER_CONFIG="imgui/imgui_config.h") target_compile_definitions(Dear_ImGui PRIVATE IMGUI_USER_CONFIG="${PROJECT_SOURCE_DIR}/src/imgui/imgui_config.h") diff --git a/src/common/config.cpp b/src/common/config.cpp index fb844b216..3f1e002e1 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -2,7 +2,9 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include #include +#include #include #include #include // for wstring support @@ -28,8 +30,13 @@ std::filesystem::path find_fs_path_or(const basic_value& v, const K& ky, } } // namespace toml +namespace po = boost::program_options; + namespace Config { +// Program options map +static po::variables_map optionMap; + static bool isNeo = false; static bool isFullscreen = false; static bool playBGM = false; @@ -42,7 +49,6 @@ static std::string logFilter; static std::string logType = "async"; static std::string userName = "shadPS4"; static std::string updateChannel; -static std::string patchFile = ""; static std::string backButtonBehavior = "left"; static bool useSpecialPad = false; static int specialPadClass = 1; @@ -89,6 +95,10 @@ bool isNeoMode() { } bool isFullscreenMode() { + if (optionMap.count("fullscreen")) { + return true; + } + return isFullscreen; } @@ -141,7 +151,11 @@ std::string getUpdateChannel() { } std::string getPatchFile() { - return patchFile; + if (optionMap.contains("patch-file")) { + return optionMap["patch-file"].as(); + } + + return ""; } std::string getBackButtonBehavior() { @@ -312,10 +326,6 @@ void setUpdateChannel(const std::string& type) { updateChannel = type; } -void setPatchFile(const std::string& fileName) { - patchFile = fileName; -} - void setBackButtonBehavior(const std::string& type) { backButtonBehavior = type; } @@ -576,15 +586,24 @@ void load(const std::filesystem::path& path) { } } -void loadArgs(int& argc, char* argv[]) { - for (int i = 0; i < argc; i++) { - const std::string arg = argv[i]; - if (arg == "-p") { - patchFile = argv[i + 1]; - } else if (arg == "-f" || arg == "--fullscreen") { - isFullscreen = true; - } +bool loadArgs(int argc, char* argv[]) { + // Declare the supported options. + std::string description = fmt::format("Usage: {} [options] ", argv[0]); + po::options_description desc(description); + auto options = desc.add_options(); + options("help", "Shows this help message"); + options("patch-file,p", po::value(), "Specifies the patch file"); + options("fullscreen,f", "Switches the emulator to fullscreen mode"); + + po::store(po::parse_command_line(argc, argv, desc), optionMap); + po::notify(optionMap); + + if (argc == 1 || optionMap.count("help")) { + std::cout << desc << "\n"; + return false; } + + return true; } void save(const std::filesystem::path& path) { @@ -690,7 +709,6 @@ void setDefaultValues() { } else { updateChannel = "Nightly"; } - patchFile = ""; cursorState = HideCursorState::Idle; cursorHideTimeout = 5; backButtonBehavior = "left"; diff --git a/src/common/config.h b/src/common/config.h index d08a85097..ae57fa9b5 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -13,7 +13,7 @@ enum HideCursorState : s16 { Never, Idle, Always }; void load(const std::filesystem::path& path); void save(const std::filesystem::path& path); -void loadArgs(int& argc, char* argv[]); +bool loadArgs(int argc, char* argv[]); bool isNeoMode(); bool isFullscreenMode(); diff --git a/src/emulator.cpp b/src/emulator.cpp index ebf7da07a..34d034513 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -256,14 +256,6 @@ void Emulator::Run(const std::filesystem::path& file) { std::exit(0); } -void Emulator::Run(int& argc, char* argv[]) { - // Load config options from arguments - Config::loadArgs(argc, argv); - MemoryPatcher::patchFile = Config::getPatchFile(); - - this->Run(argv[1]); -} - void Emulator::LoadSystemModules(const std::filesystem::path& file) { constexpr std::array ModulesToLoad{ {{"libSceNgs2.sprx", &Libraries::Ngs2::RegisterlibSceNgs2}, diff --git a/src/emulator.h b/src/emulator.h index 9a8bbf6e8..dc2959af4 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -26,7 +26,6 @@ public: ~Emulator(); void Run(const std::filesystem::path& file); - void Run(int& argc, char* argv[]); void UpdatePlayTime(const std::string& serial); private: diff --git a/src/main.cpp b/src/main.cpp index 70d2b432e..fe9c59082 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,6 +2,8 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include +#include "common/config.h" +#include "common/memory_patcher.h" #include "emulator.h" #ifdef _WIN32 @@ -13,6 +15,13 @@ int main(int argc, char* argv[]) { SetConsoleOutputCP(CP_UTF8); #endif + // Parse command line arguments + if (!Config::loadArgs(argc, argv)) { + return 0; + } + + MemoryPatcher::patchFile = Config::getPatchFile(); + if (argc == 1) { fmt::print("Usage: {} \n", argv[0]); return -1; @@ -24,7 +33,7 @@ int main(int argc, char* argv[]) { } Core::Emulator emulator; - emulator.Run(argc, argv); + emulator.Run(argv[argc - 1]); return 0; } diff --git a/src/qt_gui/main.cpp b/src/qt_gui/main.cpp index eac32724d..c491db96f 100644 --- a/src/qt_gui/main.cpp +++ b/src/qt_gui/main.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include "common/config.h" +#include "common/memory_patcher.h" #include "core/file_sys/fs.h" #include "emulator.h" #include "game_install_dialog.h" @@ -18,13 +19,19 @@ int main(int argc, char* argv[]) { #ifdef _WIN32 SetConsoleOutputCP(CP_UTF8); #endif + // Parse command line arguments + if (!Config::loadArgs(argc, argv)) { + return 0; + } - QApplication a(argc, argv); + MemoryPatcher::patchFile = Config::getPatchFile(); // Load configurations and initialize Qt application const auto user_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); Config::load(user_dir / "config.toml"); + QApplication a(argc, argv); + // Check if elf or eboot.bin path was passed as a command line argument bool has_command_line_argument = argc > 1; @@ -44,7 +51,7 @@ int main(int argc, char* argv[]) { // Check for command line arguments if (has_command_line_argument) { Core::Emulator emulator; - emulator.Run(argc, argv); + emulator.Run(argv[argc - 1]); } // Run the Qt application