diff --git a/.gitmodules b/.gitmodules index 868632298..2bf62e6b1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,9 +16,6 @@ [submodule "third_party/catch"] path = third_party/catch url = https://github.com/catchorg/Catch2.git -[submodule "third_party/gflags"] - path = third_party/gflags - url = https://github.com/benvanik/gflags.git [submodule "third_party/premake-core"] path = third_party/premake-core url = https://github.com/xenia-project/premake-core.git @@ -49,3 +46,9 @@ [submodule "third_party/capstone"] path = third_party/capstone url = https://github.com/xenia-project/capstone.git +[submodule "third_party/cpptoml"] + path = third_party/cpptoml + url = https://github.com/skystrife/cpptoml +[submodule "third_party/cxxopts"] + path = third_party/cxxopts + url = https://github.com/jarro2783/cxxopts diff --git a/premake5.lua b/premake5.lua index 30d26b04f..24c783782 100644 --- a/premake5.lua +++ b/premake5.lua @@ -193,30 +193,9 @@ filter("platforms:Windows") "dxguid", }) --- Create scratch/ path and dummy flags file if needed. +-- Create scratch/ path if not os.isdir("scratch") then os.mkdir("scratch") - local flags_file = io.open("scratch/flags.txt", "w") - flags_file:write("# Put flags, one on each line.\n") - flags_file:write("# Launch executables with --flags_file=scratch/flags.txt\n") - flags_file:write("\n") - flags_file:write("--cpu=x64\n") - flags_file:write("#--enable_haswell_instructions=false\n") - flags_file:write("\n") - flags_file:write("--debug\n") - flags_file:write("#--protect_zero=false\n") - flags_file:write("\n") - flags_file:write("#--mute\n") - flags_file:write("\n") - flags_file:write("--fast_stdout\n") - flags_file:write("#--flush_stdout=false\n") - flags_file:write("\n") - flags_file:write("#--vsync=false\n") - flags_file:write("#--trace_gpu_prefix=scratch/gpu/gpu_trace_\n") - flags_file:write("#--trace_gpu_stream\n") - flags_file:write("#--disable_framebuffer_readback\n") - flags_file:write("\n") - flags_file:close() end solution("xenia") @@ -237,12 +216,12 @@ solution("xenia") end configurations({"Checked", "Debug", "Release"}) - -- Include third party files first so they don't have to deal with gflags. include("third_party/aes_128.lua") include("third_party/capstone.lua") include("third_party/dxbc.lua") include("third_party/discord-rpc.lua") - include("third_party/gflags.lua") + include("third_party/cxxopts.lua") + include("third_party/cpptoml.lua") include("third_party/glew.lua") include("third_party/glslang-spirv.lua") include("third_party/imgui.lua") diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 882f4caa9..daf973fb6 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include "xenia/app/emulator_window.h" // Autogenerated by `xb premake`. @@ -17,6 +15,7 @@ #include "third_party/imgui/imgui.h" #include "xenia/app/discord/discord_presence.h" #include "xenia/base/clock.h" +#include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/logging.h" #include "xenia/base/platform.h" @@ -29,7 +28,8 @@ #include "xenia/ui/imgui_dialog.h" #include "xenia/ui/imgui_drawer.h" -DEFINE_bool(discord, false, "Enable Discord rich presence"); +DECLARE_bool(debug); +DEFINE_bool(discord, false, "Enable Discord rich presence", "General"); namespace xe { namespace app { @@ -85,7 +85,7 @@ bool EmulatorWindow::Initialize() { return false; } - if (FLAGS_discord) { + if (cvars::discord) { discord::DiscordPresence::InitializeDiscord(); discord::DiscordPresence::NotPlaying(); } @@ -344,7 +344,7 @@ void EmulatorWindow::FileOpen() { void EmulatorWindow::FileClose() { if (emulator_->is_title_open()) { emulator_->TerminateTitle(); - if (FLAGS_discord) { + if (cvars::discord) { discord::DiscordPresence::NotPlaying(); } } @@ -398,7 +398,7 @@ void EmulatorWindow::CpuTimeScalarSetDouble() { } void EmulatorWindow::CpuBreakIntoDebugger() { - if (!FLAGS_debug) { + if (!cvars::debug) { xe::ui::ImGuiDialog::ShowMessageBox(window_.get(), "Xenia Debugger", "Xenia must be launched with the " "--debug flag in order to enable " @@ -444,7 +444,7 @@ void EmulatorWindow::UpdateTitle() { auto game_title = emulator()->game_title(); title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(), game_title.c_str()); - if (FLAGS_discord) { + if (cvars::discord) { discord::DiscordPresence::PlayingTitle(game_title); } } diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 8f9447626..7fa8c7050 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -12,7 +12,6 @@ project("xenia-app") "capstone", "dxbc", "discord-rpc", - "gflags", "glew", "glslang-spirv", "imgui", @@ -46,9 +45,6 @@ project("xenia-app") "XBYAK_NO_OP_NAMES", "XBYAK_ENABLE_OMITTED_OPERAND", }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() files({ "xenia_main.cc", @@ -92,6 +88,5 @@ project("xenia-app") if not os.isfile(user_file) then debugdir(project_root) debugargs({ - "--flagfile=scratch/flags.txt", }) end diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc index 6bd5e91e7..4c1744c6d 100644 --- a/src/xenia/app/xenia_main.cc +++ b/src/xenia/app/xenia_main.cc @@ -7,14 +7,14 @@ ****************************************************************************** */ -#include - #include "xenia/app/emulator_window.h" +#include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" #include "xenia/base/profiling.h" #include "xenia/base/threading.h" +#include "xenia/config.h" #include "xenia/debug/ui/debug_window.h" #include "xenia/emulator.h" #include "xenia/ui/file_picker.h" @@ -40,26 +40,33 @@ #include "xenia/hid/xinput/xinput_hid.h" #endif // XE_PLATFORM_WIN32 -DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]"); -DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]"); -DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]"); +#include "third_party/xbyak/xbyak/xbyak_util.h" -DEFINE_string(target, "", "Specifies the target .xex or .iso to execute."); -DEFINE_bool(fullscreen, false, "Toggles fullscreen"); +DEFINE_string(apu, "any", "Audio system. Use: [any, nop, xaudio2]", "General"); +DEFINE_string(gpu, "any", "Graphics system. Use: [any, vulkan, null]", + "General"); +DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]", + "General"); -DEFINE_string(content_root, "", "Root path for content (save/etc) storage."); +DEFINE_bool(fullscreen, false, "Toggles fullscreen", "General"); -DEFINE_bool(mount_scratch, false, "Enable scratch mount"); -DEFINE_bool(mount_cache, false, "Enable cache mount"); +DEFINE_string(content_root, "", "Root path for content (save/etc) storage.", + "General"); + +DEFINE_bool(mount_scratch, false, "Enable scratch mount", "General"); +DEFINE_bool(mount_cache, false, "Enable cache mount", "General"); + +CmdVar(target, "", "Specifies the target .xex or .iso to execute."); +DECLARE_bool(debug); namespace xe { namespace app { std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { - if (FLAGS_apu.compare("nop") == 0) { + if (cvars::apu.compare("nop") == 0) { return apu::nop::NopAudioSystem::Create(processor); #if XE_PLATFORM_WIN32 - } else if (FLAGS_apu.compare("xaudio2") == 0) { + } else if (cvars::apu.compare("xaudio2") == 0) { return apu::xaudio2::XAudio2AudioSystem::Create(processor); #endif // XE_PLATFORM_WIN32 } else { @@ -79,15 +86,15 @@ std::unique_ptr CreateAudioSystem(cpu::Processor* processor) { } std::unique_ptr CreateGraphicsSystem() { - if (FLAGS_gpu.compare("vulkan") == 0) { + if (cvars::gpu.compare("vulkan") == 0) { return std::unique_ptr( new xe::gpu::vulkan::VulkanGraphicsSystem()); #if XE_PLATFORM_WIN32 - } else if (FLAGS_gpu.compare("d3d12") == 0) { + } else if (cvars::gpu.compare("d3d12") == 0) { return std::unique_ptr( new xe::gpu::d3d12::D3D12GraphicsSystem()); #endif // XE_PLATFORM_WIN32 - } else if (FLAGS_gpu.compare("null") == 0) { + } else if (cvars::gpu.compare("null") == 0) { return std::unique_ptr( new xe::gpu::null::NullGraphicsSystem()); } else { @@ -115,12 +122,12 @@ std::unique_ptr CreateGraphicsSystem() { std::vector> CreateInputDrivers( ui::Window* window) { std::vector> drivers; - if (FLAGS_hid.compare("nop") == 0) { + if (cvars::hid.compare("nop") == 0) { drivers.emplace_back(xe::hid::nop::Create(window)); #if XE_PLATFORM_WIN32 - } else if (FLAGS_hid.compare("winkey") == 0) { + } else if (cvars::hid.compare("winkey") == 0) { drivers.emplace_back(xe::hid::winkey::Create(window)); - } else if (FLAGS_hid.compare("xinput") == 0) { + } else if (cvars::hid.compare("xinput") == 0) { drivers.emplace_back(xe::hid::xinput::Create(window)); #endif // XE_PLATFORM_WIN32 } else { @@ -154,16 +161,17 @@ int xenia_main(const std::vector& args) { Profiler::ThreadEnter("main"); // Figure out where content should go. - std::wstring content_root; - if (!FLAGS_content_root.empty()) { - content_root = xe::to_wstring(FLAGS_content_root); - } else { + std::wstring content_root = xe::to_wstring(cvars::content_root); + std::wstring config_folder; + + if (content_root.empty()) { auto base_path = xe::filesystem::GetExecutableFolder(); base_path = xe::to_absolute_path(base_path); auto portable_path = xe::join_paths(base_path, L"portable.txt"); if (xe::filesystem::PathExists(portable_path)) { content_root = xe::join_paths(base_path, L"content"); + config_folder = base_path; } else { content_root = xe::filesystem::GetUserFolder(); #if defined(XE_PLATFORM_WIN32) @@ -174,11 +182,14 @@ int xenia_main(const std::vector& args) { #warning Unhandled platform for content root. content_root = xe::join_paths(content_root, L"Xenia"); #endif + config_folder = content_root; content_root = xe::join_paths(content_root, L"content"); } } content_root = xe::to_absolute_path(content_root); + XELOGI("Content root: %S", content_root.c_str()); + config::SetupConfig(config_folder); // Create the emulator but don't initialize so we can setup the window. auto emulator = std::make_unique(L"", content_root); @@ -196,7 +207,7 @@ int xenia_main(const std::vector& args) { return 1; } - if (FLAGS_mount_scratch) { + if (cvars::mount_scratch) { auto scratch_device = std::make_unique( "\\SCRATCH", L"scratch", false); if (!scratch_device->Initialize()) { @@ -210,7 +221,7 @@ int xenia_main(const std::vector& args) { } } - if (FLAGS_mount_cache) { + if (cvars::mount_cache) { auto cache0_device = std::make_unique("\\CACHE0", L"cache0", false); if (!cache0_device->Initialize()) { @@ -239,7 +250,7 @@ int xenia_main(const std::vector& args) { // Set a debug handler. // This will respond to debugging requests so we can open the debug UI. std::unique_ptr debug_window; - if (FLAGS_debug) { + if (cvars::debug) { emulator->processor()->set_debug_listener_request_handler( [&](xe::cpu::Processor* processor) { if (debug_window) { @@ -285,20 +296,12 @@ int xenia_main(const std::vector& args) { // Grab path from the flag or unnamed argument. std::wstring path; - if (!FLAGS_target.empty() || args.size() >= 2) { - if (!FLAGS_target.empty()) { - // Passed as a named argument. - // TODO(benvanik): find something better than gflags that supports - // unicode. - path = xe::to_wstring(FLAGS_target); - } else { - // Passed as an unnamed argument. - path = args[1]; - } + if (!cvars::target.empty()) { + path = xe::to_wstring(cvars::target); } // Toggles fullscreen - if (FLAGS_fullscreen) emulator_window->ToggleFullscreen(); + if (cvars::fullscreen) emulator_window->ToggleFullscreen(); if (!path.empty()) { // Normalize the path and make absolute. diff --git a/src/xenia/apu/apu_flags.cc b/src/xenia/apu/apu_flags.cc index 927526bb0..63948f3a4 100644 --- a/src/xenia/apu/apu_flags.cc +++ b/src/xenia/apu/apu_flags.cc @@ -9,4 +9,4 @@ #include "xenia/apu/apu_flags.h" -DEFINE_bool(mute, false, "Mutes all audio output."); +DEFINE_bool(mute, false, "Mutes all audio output.", "Audio") diff --git a/src/xenia/apu/apu_flags.h b/src/xenia/apu/apu_flags.h index d85d67b7e..d48a32dcb 100644 --- a/src/xenia/apu/apu_flags.h +++ b/src/xenia/apu/apu_flags.h @@ -10,8 +10,7 @@ #ifndef XENIA_APU_APU_FLAGS_H_ #define XENIA_APU_APU_FLAGS_H_ -#include - -DECLARE_bool(mute); +#include "xenia/base/cvar.h" +DECLARE_bool(mute) #endif // XENIA_APU_APU_FLAGS_H_ diff --git a/src/xenia/apu/nop/nop_apu_flags.h b/src/xenia/apu/nop/nop_apu_flags.h index 448aaeeef..5a2da249c 100644 --- a/src/xenia/apu/nop/nop_apu_flags.h +++ b/src/xenia/apu/nop/nop_apu_flags.h @@ -10,6 +10,4 @@ #ifndef XENIA_APU_NOP_NOP_APU_FLAGS_H_ #define XENIA_APU_NOP_NOP_APU_FLAGS_H_ -#include - #endif // XENIA_APU_NOP_NOP_APU_FLAGS_H_ diff --git a/src/xenia/apu/nop/premake5.lua b/src/xenia/apu/nop/premake5.lua index 21eb100e8..8c16c8a65 100644 --- a/src/xenia/apu/nop/premake5.lua +++ b/src/xenia/apu/nop/premake5.lua @@ -12,7 +12,4 @@ project("xenia-apu-nop") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/apu/premake5.lua b/src/xenia/apu/premake5.lua index 17ecd8834..a3284fe0e 100644 --- a/src/xenia/apu/premake5.lua +++ b/src/xenia/apu/premake5.lua @@ -14,7 +14,6 @@ project("xenia-apu") defines({ }) includedirs({ - project_root.."/third_party/gflags/src", project_root.."/third_party/libav/", }) local_platform_files() diff --git a/src/xenia/apu/xaudio2/premake5.lua b/src/xenia/apu/xaudio2/premake5.lua index 57bd6e1ef..9198a9a4a 100644 --- a/src/xenia/apu/xaudio2/premake5.lua +++ b/src/xenia/apu/xaudio2/premake5.lua @@ -12,7 +12,4 @@ project("xenia-apu-xaudio2") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/apu/xaudio2/xaudio2_apu_flags.h b/src/xenia/apu/xaudio2/xaudio2_apu_flags.h index 786abb64d..f491f5d01 100644 --- a/src/xenia/apu/xaudio2/xaudio2_apu_flags.h +++ b/src/xenia/apu/xaudio2/xaudio2_apu_flags.h @@ -10,6 +10,4 @@ #ifndef XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ #define XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ -#include - #endif // XENIA_APU_XAUDIO2_XAUDIO2_APU_FLAGS_H_ diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc index 89447c7b3..fe3f8bd10 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc +++ b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc @@ -151,7 +151,7 @@ bool XAudio2AudioDriver::Initialize() { return false; } - if (FLAGS_mute) { + if (cvars::mute) { pcm_voice_->SetVolume(0.0f); } diff --git a/src/xenia/apu/xma_decoder.cc b/src/xenia/apu/xma_decoder.cc index bb8e46756..00a408c1f 100644 --- a/src/xenia/apu/xma_decoder.cc +++ b/src/xenia/apu/xma_decoder.cc @@ -9,9 +9,8 @@ #include "xenia/apu/xma_decoder.h" -#include - #include "xenia/apu/xma_context.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/profiling.h" @@ -49,7 +48,8 @@ extern "C" { // do this, it's likely they are either passing the context to XAudio or // using the XMA* functions. -DEFINE_bool(libav_verbose, false, "Verbose libav output (debug and above)"); +DEFINE_bool(libav_verbose, false, "Verbose libav output (debug and above)", + "Audio"); namespace xe { namespace apu { @@ -60,7 +60,7 @@ XmaDecoder::XmaDecoder(cpu::Processor* processor) XmaDecoder::~XmaDecoder() = default; void av_log_callback(void* avcl, int level, const char* fmt, va_list va) { - if (!FLAGS_libav_verbose && level > AV_LOG_WARNING) { + if (!cvars::libav_verbose && level > AV_LOG_WARNING) { return; } diff --git a/src/xenia/base/cvar.cc b/src/xenia/base/cvar.cc new file mode 100644 index 000000000..d7c82c970 --- /dev/null +++ b/src/xenia/base/cvar.cc @@ -0,0 +1,56 @@ +#include "cvar.h" + +namespace cvar { +cxxopts::Options options("xenia", "Xbox 360 Emulator"); +std::map* CmdVars; +std::map* ConfigVars; + +void PrintHelpAndExit() { + std::cout << options.help({""}) << std::endl; + std::cout << "For the full list of command line arguments, see xenia.cfg." + << std::endl; + exit(0); +} + +void ParseLaunchArguments(int argc, char** argv) { + options.add_options()("help", "Prints help and exit."); + if (!CmdVars) CmdVars = new std::map(); + if (!ConfigVars) ConfigVars = new std::map(); + for (auto& it : *CmdVars) { + auto cmdVar = it.second; + cmdVar->AddToLaunchOptions(&options); + } + std::vector vars; + for (const auto& s : *ConfigVars) vars.push_back(s.second); + + for (auto& it : *ConfigVars) { + auto configVar = it.second; + configVar->AddToLaunchOptions(&options); + } + try { + options.positional_help("[Path to .iso/.xex]"); + options.parse_positional({"target"}); + + auto result = options.parse(argc, argv); + if (result.count("help")) { + PrintHelpAndExit(); + } + for (auto& it : *CmdVars) { + auto cmdVar = static_cast(it.second); + if (result.count(cmdVar->GetName())) { + cmdVar->LoadFromLaunchOptions(&result); + } + } + for (auto& it : *ConfigVars) { + auto configVar = static_cast(it.second); + if (result.count(configVar->GetName())) { + configVar->LoadFromLaunchOptions(&result); + } + } + } catch (const cxxopts::OptionException& e) { + std::cout << e.what() << std::endl; + PrintHelpAndExit(); + } +} + +} // namespace cvar diff --git a/src/xenia/base/cvar.h b/src/xenia/base/cvar.h new file mode 100644 index 000000000..4661671d9 --- /dev/null +++ b/src/xenia/base/cvar.h @@ -0,0 +1,258 @@ +#ifndef XENIA_CVAR_H_ +#define XENIA_CVAR_H_ +#include +#include +#include "cpptoml/include/cpptoml.h" +#include "cxxopts/include/cxxopts.hpp" +#include "xenia/base/string_util.h" +namespace cvar { + +class ICommandVar { + public: + virtual ~ICommandVar() = default; + virtual std::string GetName() = 0; + virtual std::string GetDescription() = 0; + virtual void UpdateValue() = 0; + virtual void AddToLaunchOptions(cxxopts::Options* options) = 0; + virtual void LoadFromLaunchOptions(cxxopts::ParseResult* result) = 0; +}; + +class IConfigVar : virtual public ICommandVar { + public: + virtual std::string GetCategory() = 0; + virtual std::string GetConfigValue() = 0; + virtual void LoadConfigValue(std::shared_ptr result) = 0; + virtual void LoadGameConfigValue(std::shared_ptr result) = 0; +}; + +template +class CommandVar : virtual public ICommandVar { + public: + CommandVar(const char* name, T* defaultValue, const char* description); + std::string GetName() override; + std::string GetDescription() override; + void AddToLaunchOptions(cxxopts::Options* options) override; + void LoadFromLaunchOptions(cxxopts::ParseResult* result) override; + T* GetCurrentValue() { return currentValue_; } + + protected: + std::string name_; + T defaultValue_; + T* currentValue_; + std::unique_ptr commandLineValue_; + std::string description_; + T Convert(std::string val); + static std::string ToString(T val); + void SetValue(T val); + void SetCommandLineValue(T val); + void UpdateValue() override; +}; +#pragma warning(push) +#pragma warning(disable : 4250) +template +class ConfigVar : public CommandVar, virtual public IConfigVar { + public: + ConfigVar(const char* name, T* defaultValue, const char* description, + const char* category); + std::string GetConfigValue() override; + std::string GetCategory() override; + void AddToLaunchOptions(cxxopts::Options* options) override; + void LoadConfigValue(std::shared_ptr result) override; + void LoadGameConfigValue(std::shared_ptr result) override; + void SetConfigValue(T val); + void SetGameConfigValue(T val); + + private: + std::string category_; + std::unique_ptr configValue_ = nullptr; + std::unique_ptr gameConfigValue_ = nullptr; + void UpdateValue() override; +}; + +#pragma warning(pop) +template +std::string CommandVar::GetName() { + return name_; +} +template +std::string CommandVar::GetDescription() { + return description_; +} +template +void CommandVar::AddToLaunchOptions(cxxopts::Options* options) { + options->add_options()(this->name_, this->description_, cxxopts::value()); +} +template +void ConfigVar::AddToLaunchOptions(cxxopts::Options* options) { + options->add_options(category_)(this->name_, this->description_, + cxxopts::value()); +} +template +void CommandVar::LoadFromLaunchOptions(cxxopts::ParseResult* result) { + T value = (*result)[this->name_].template as(); + SetCommandLineValue(value); +} +template +void ConfigVar::LoadConfigValue(std::shared_ptr result) { + SetConfigValue(*cpptoml::get_impl(result)); +} +template +void ConfigVar::LoadGameConfigValue(std::shared_ptr result) { + SetGameConfigValue(*cpptoml::get_impl(result)); +} +template +CommandVar::CommandVar(const char* name, T* defaultValue, + const char* description) + : name_(name), + defaultValue_(*defaultValue), + description_(description), + currentValue_(defaultValue) {} + +template +ConfigVar::ConfigVar(const char* name, T* defaultValue, + const char* description, const char* category) + : CommandVar(name, defaultValue, description), category_(category) {} + +template +void CommandVar::UpdateValue() { + if (this->commandLineValue_) return this->SetValue(*this->commandLineValue_); + return this->SetValue(defaultValue_); +} +template +void ConfigVar::UpdateValue() { + if (this->commandLineValue_) return this->SetValue(*this->commandLineValue_); + if (this->gameConfigValue_) return this->SetValue(*this->gameConfigValue_); + if (this->configValue_) return this->SetValue(*this->configValue_); + return this->SetValue(this->defaultValue_); +} +template +T CommandVar::Convert(std::string val) { + return xe::string_util::from_string(val); +} +template <> +inline std::string CommandVar::Convert(std::string val) { + return val; +} + +template <> +inline std::string CommandVar::ToString(bool val) { + return val ? "true" : "false"; +} +template <> +inline std::string CommandVar::ToString(std::string val) { + return "\"" + val + "\""; +} + +template +std::string CommandVar::ToString(T val) { + return std::to_string(val); +} + +template +void CommandVar::SetValue(T val) { + *currentValue_ = val; +} +template +std::string ConfigVar::GetCategory() { + return category_; +} +template +std::string ConfigVar::GetConfigValue() { + if (this->configValue_) return this->ToString(*this->configValue_); + return this->ToString(this->defaultValue_); +} +template +void CommandVar::SetCommandLineValue(const T val) { + this->commandLineValue_ = std::make_unique(val); + this->UpdateValue(); +} +template +void ConfigVar::SetConfigValue(T val) { + this->configValue_ = std::make_unique(val); + this->UpdateValue(); +} +template +void ConfigVar::SetGameConfigValue(T val) { + this->gameConfigValue_ = std::make_unique(val); + this->UpdateValue(); +} + +extern std::map* CmdVars; +extern std::map* ConfigVars; + +inline void AddConfigVar(IConfigVar* cv) { + if (!ConfigVars) ConfigVars = new std::map(); + ConfigVars->insert(std::pair(cv->GetName(), cv)); +} +inline void AddCommandVar(ICommandVar* cv) { + if (!CmdVars) CmdVars = new std::map(); + CmdVars->insert(std::pair(cv->GetName(), cv)); +} +void ParseLaunchArguments(int argc, char** argv); + +template +T* define_configvar(const char* name, T* defaultValue, const char* description, + const char* category) { + IConfigVar* cfgVar = + new ConfigVar(name, defaultValue, description, category); + AddConfigVar(cfgVar); + return defaultValue; +} + +template +T* define_cmdvar(const char* name, T* defaultValue, const char* description) { + ICommandVar* cmdVar = new CommandVar(name, defaultValue, description); + AddCommandVar(cmdVar); + return defaultValue; +} +#define DEFINE_double(name, defaultValue, description, category) \ + DEFINE_CVar(name, defaultValue, description, category, double) + +#define DEFINE_int32(name, defaultValue, description, category) \ + DEFINE_CVar(name, defaultValue, description, category, int32_t) + +#define DEFINE_uint64(name, defaultValue, description, category) \ + DEFINE_CVar(name, defaultValue, description, category, uint64_t) + +#define DEFINE_string(name, defaultValue, description, category) \ + DEFINE_CVar(name, defaultValue, description, category, std::string) + +#define DEFINE_bool(name, defaultValue, description, category) \ + DEFINE_CVar(name, defaultValue, description, category, bool) + +#define DEFINE_CVar(name, defaultValue, description, category, type) \ + namespace cvars { \ + type name = defaultValue; \ + } \ + namespace cv { \ + static auto cv_##name = \ + cvar::define_configvar(#name, &cvars::name, description, category); \ + } + +// CmdVars can only be strings for now, we don't need any others +#define CmdVar(name, defaultValue, description) \ + namespace cvars { \ + std::string name = defaultValue; \ + } \ + namespace cv { \ + static auto cv_##name = \ + cvar::define_cmdvar(#name, &cvars::name, description); \ + } + +#define DECLARE_double(name) DECLARE_CVar(name, double) + +#define DECLARE_bool(name) DECLARE_CVar(name, bool) + +#define DECLARE_string(name) DECLARE_CVar(name, std::string) + +#define DECLARE_int32(name) DECLARE_CVar(name, int32_t) + +#define DECLARE_uint64(name) DECLARE_CVar(name, uint64_t) + +#define DECLARE_CVar(name, type) \ + namespace cvars { \ + extern type name; \ + } + +} // namespace cvar +#endif // XENIA_CVAR_H_ diff --git a/src/xenia/base/logging.cc b/src/xenia/base/logging.cc index 4cd495022..bb8f57100 100644 --- a/src/xenia/base/logging.cc +++ b/src/xenia/base/logging.cc @@ -9,8 +9,6 @@ #include "xenia/base/logging.h" -#include - #include #include #include @@ -19,6 +17,7 @@ #include #include "xenia/base/atomic.h" +#include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/filesystem.h" #include "xenia/base/main.h" @@ -26,6 +25,7 @@ #include "xenia/base/memory.h" #include "xenia/base/ring_buffer.h" #include "xenia/base/threading.h" +//#include "xenia/base/cvar.h" // For MessageBox: // TODO(benvanik): generic API? logging_win.cc? @@ -35,12 +35,15 @@ DEFINE_string( log_file, "", - "Logs are written to the given file (specify stdout for command line)"); -DEFINE_bool(log_debugprint, false, "Dump the log to DebugPrint."); -DEFINE_bool(flush_log, true, "Flush log file after each log line batch."); + "Logs are written to the given file (specify stdout for command line)", + "Logging"); +DEFINE_bool(log_debugprint, false, "Dump the log to DebugPrint.", "Logging"); +DEFINE_bool(flush_log, true, "Flush log file after each log line batch.", + "Logging"); DEFINE_int32( log_level, 2, - "Maximum level to be logged. (0=error, 1=warning, 2=info, 3=debug)"); + "Maximum level to be logged. (0=error, 1=warning, 2=info, 3=debug)", + "Logging"); namespace xe { @@ -52,16 +55,16 @@ thread_local std::vector log_format_buffer_(64 * 1024); class Logger { public: explicit Logger(const std::wstring& app_name) : running_(true) { - if (FLAGS_log_file.empty()) { + if (cvars::log_file.empty()) { // Default to app name. auto file_path = app_name + L".log"; xe::filesystem::CreateParentFolder(file_path); file_ = xe::filesystem::OpenFile(file_path, "wt"); } else { - if (FLAGS_log_file == "stdout") { + if (cvars::log_file == "stdout") { file_ = stdout; } else { - auto file_path = xe::to_wstring(FLAGS_log_file.c_str()); + auto file_path = xe::to_wstring(cvars::log_file); xe::filesystem::CreateParentFolder(file_path); file_ = xe::filesystem::OpenFile(file_path, "wt"); } @@ -81,7 +84,7 @@ class Logger { void AppendLine(uint32_t thread_id, LogLevel level, const char prefix_char, const char* buffer, size_t buffer_length) { - if (static_cast(level) > FLAGS_log_level) { + if (static_cast(level) > cvars::log_level) { // Discard this line. return; } @@ -148,7 +151,7 @@ class Logger { fwrite(buf, 1, size, file_); } - if (FLAGS_log_debugprint) { + if (cvars::log_debugprint) { debugging::DebugPrint("%.*s", size, buf); } } @@ -214,7 +217,7 @@ class Logger { read_head_ = rb.read_offset(); } if (did_write) { - if (FLAGS_flush_log) { + if (cvars::flush_log) { fflush(file_); } diff --git a/src/xenia/base/main_posix.cc b/src/xenia/base/main_posix.cc index 55dfae745..1a56b57c2 100644 --- a/src/xenia/base/main_posix.cc +++ b/src/xenia/base/main_posix.cc @@ -7,10 +7,9 @@ ****************************************************************************** */ +#include "xenia/base/cvar.h" #include "xenia/base/main.h" -#include - #include "xenia/base/logging.h" #include "xenia/base/string.h" @@ -23,10 +22,7 @@ bool has_console_attached() { return true; } extern "C" int main(int argc, char** argv) { auto entry_info = xe::GetEntryInfo(); - google::SetUsageMessage(std::string("usage: ") + - xe::to_string(entry_info.usage)); - google::SetVersionString("1.0"); - google::ParseCommandLineFlags(&argc, &argv, true); + cvar::ParseLaunchArguments(argc, argv); std::vector args; for (int n = 0; n < argc; n++) { @@ -39,6 +35,5 @@ extern "C" int main(int argc, char** argv) { // Call app-provided entry point. int result = entry_info.entry_point(args); - google::ShutDownCommandLineFlags(); return result; } diff --git a/src/xenia/base/main_win.cc b/src/xenia/base/main_win.cc index c52df8a91..3c373a7df 100644 --- a/src/xenia/base/main_win.cc +++ b/src/xenia/base/main_win.cc @@ -10,7 +10,6 @@ #include "xenia/base/main.h" #include -#include #include #include @@ -18,6 +17,7 @@ // Autogenerated by `xb premake`. #include "build/version.h" +#include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/platform_win.h" #include "xenia/base/string.h" @@ -25,9 +25,10 @@ #include "third_party/xbyak/xbyak/xbyak_util.h" #include +#include "xenia/base/cvar.h" DEFINE_bool(win32_high_freq, true, - "Requests high performance from the NT kernel"); + "Requests high performance from the NT kernel", "Kernel"); namespace xe { @@ -88,7 +89,6 @@ int Main() { auto entry_info = xe::GetEntryInfo(); // Convert command line to an argv-like format so we can share code/use - // gflags. auto command_line = GetCommandLineW(); int argc; wchar_t** argv = CommandLineToArgvW(command_line, &argc); @@ -96,11 +96,7 @@ int Main() { return 1; } - google::SetUsageMessage(std::string("usage: ") + - xe::to_string(entry_info.usage)); - google::SetVersionString("1.0"); - - // Convert all args to narrow, as gflags doesn't support wchar. + // Convert all args to narrow, as cxxopts doesn't support wchar. int argca = argc; char** argva = reinterpret_cast(alloca(sizeof(char*) * argca)); for (int n = 0; n < argca; n++) { @@ -109,8 +105,7 @@ int Main() { std::wcstombs(argva[n], argv[n], len + 1); } - // Parse flags; this may delete some of them. - google::ParseCommandLineFlags(&argc, &argva, true); + cvar::ParseLaunchArguments(argca, argva); // Widen all remaining flags and convert to usable strings. std::vector args; @@ -143,7 +138,7 @@ int Main() { XE_BUILD_DATE); // Request high performance timing. - if (FLAGS_win32_high_freq) { + if (cvars::win32_high_freq) { RequestHighPerformance(); } @@ -151,7 +146,6 @@ int Main() { int result = entry_info.entry_point(args); xe::ShutdownLogging(); - google::ShutDownCommandLineFlags(); LocalFree(argv); return result; } diff --git a/src/xenia/base/premake5.lua b/src/xenia/base/premake5.lua index 960a6500c..3459f66ad 100644 --- a/src/xenia/base/premake5.lua +++ b/src/xenia/base/premake5.lua @@ -7,9 +7,6 @@ project("xenia-base") language("C++") defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() removefiles({"main_*.cc"}) files({ diff --git a/src/xenia/base/profiling.cc b/src/xenia/base/profiling.cc index e40ce177d..64eed5312 100644 --- a/src/xenia/base/profiling.cc +++ b/src/xenia/base/profiling.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include // NOTE: this must be included before microprofile as macro expansion needs @@ -30,6 +28,7 @@ #include "third_party/microprofile/microprofile.h" #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/profiling.h" #include "xenia/ui/window.h" @@ -42,7 +41,7 @@ #include "xenia/ui/microprofile_drawer.h" #endif // XE_OPTION_PROFILING_UI -DEFINE_bool(show_profiler, false, "Show profiling UI by default."); +DEFINE_bool(show_profiler, false, "Show profiling UI by default.", "Other"); namespace xe { @@ -77,7 +76,7 @@ void Profiler::Initialize() { g_MicroProfileUI.bShowSpikes = true; g_MicroProfileUI.nOpacityBackground = 0x40u << 24; g_MicroProfileUI.nOpacityForeground = 0xc0u << 24; - if (FLAGS_show_profiler) { + if (cvars::show_profiler) { MicroProfileSetDisplayMode(1); } #else diff --git a/src/xenia/base/string_util.h b/src/xenia/base/string_util.h index c65e3de57..9b03527f2 100644 --- a/src/xenia/base/string_util.h +++ b/src/xenia/base/string_util.h @@ -24,13 +24,13 @@ namespace string_util { inline std::string to_hex_string(uint32_t value) { char buffer[21]; - std::snprintf(buffer, sizeof(buffer), "%08" PRIX32, value); + snprintf(buffer, sizeof(buffer), "%08" PRIX32, value); return std::string(buffer); } inline std::string to_hex_string(uint64_t value) { char buffer[21]; - std::snprintf(buffer, sizeof(buffer), "%016" PRIX64, value); + snprintf(buffer, sizeof(buffer), "%016" PRIX64, value); return std::string(buffer); } @@ -54,8 +54,8 @@ inline std::string to_hex_string(double value) { inline std::string to_hex_string(const vec128_t& value) { char buffer[128]; - std::snprintf(buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", - value.u32[0], value.u32[1], value.u32[2], value.u32[3]); + snprintf(buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", value.u32[0], + value.u32[1], value.u32[2], value.u32[3]); return std::string(buffer); } @@ -66,7 +66,7 @@ inline std::string to_hex_string(const __m128& value) { char buffer[128]; float f[4]; _mm_storeu_ps(f, value); - std::snprintf( + snprintf( buffer, sizeof(buffer), "[%.8X, %.8X, %.8X, %.8X]", *reinterpret_cast(&f[0]), *reinterpret_cast(&f[1]), *reinterpret_cast(&f[2]), *reinterpret_cast(&f[3])); @@ -77,15 +77,22 @@ inline std::string to_string(const __m128& value) { char buffer[128]; float f[4]; _mm_storeu_ps(f, value); - std::snprintf(buffer, sizeof(buffer), "(%F, %F, %F, %F)", f[0], f[1], f[2], - f[3]); + snprintf(buffer, sizeof(buffer), "(%F, %F, %F, %F)", f[0], f[1], f[2], f[3]); return std::string(buffer); } #endif template -inline T from_string(const char* value, bool force_hex = false); +inline T from_string(const char* value, bool force_hex = false) { + // Missing implementation for converting type T to string + throw; +} + +template <> +inline bool from_string(const char* value, bool force_hex) { + return std::strcmp(value, "true") == 0 || value[0] == '1'; +} template <> inline int32_t from_string(const char* value, bool force_hex) { diff --git a/src/xenia/base/testing/premake5.lua b/src/xenia/base/testing/premake5.lua index e432d7ec4..9570a76f5 100644 --- a/src/xenia/base/testing/premake5.lua +++ b/src/xenia/base/testing/premake5.lua @@ -2,9 +2,6 @@ project_root = "../../../.." include(project_root.."/tools/build") test_suite("xenia-base-tests", project_root, ".", { - includedirs = { - project_root.."/third_party/gflags/src", - }, links = { "xenia-base", }, diff --git a/src/xenia/base/vec128.h b/src/xenia/base/vec128.h index 68d06744a..8779ade80 100644 --- a/src/xenia/base/vec128.h +++ b/src/xenia/base/vec128.h @@ -266,8 +266,8 @@ static inline vec128_t vec128b(uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3, inline std::string to_string(const vec128_t& value) { char buffer[128]; - std::snprintf(buffer, sizeof(buffer), "(%g, %g, %g, %g)", value.x, value.y, - value.z, value.w); + snprintf(buffer, sizeof(buffer), "(%g, %g, %g, %g)", value.x, value.y, + value.z, value.w); return std::string(buffer); } diff --git a/src/xenia/config.cc b/src/xenia/config.cc new file mode 100644 index 000000000..e068f3109 --- /dev/null +++ b/src/xenia/config.cc @@ -0,0 +1,126 @@ +#include "config.h" +#include "cpptoml/include/cpptoml.h" +#include "xenia/base/cvar.h" +#include "xenia/base/filesystem.h" +#include "xenia/base/logging.h" +#include "xenia/base/string.h" + +CmdVar(config, "", "Specifies the target config to load."); +namespace config { +std::wstring config_name = L"xenia.config.toml"; +std::wstring config_folder; +std::wstring config_path; + +bool sortCvar(cvar::IConfigVar* a, cvar::IConfigVar* b) { + if (a->GetCategory() < b->GetCategory()) return true; + if (a->GetCategory() > b->GetCategory()) return false; + if (a->GetName() < b->GetName()) return true; + return false; +} + +std::shared_ptr ParseConfig(std::string config_path) { + try { + return cpptoml::parse_file(config_path); + } catch (cpptoml::parse_exception) { + xe::FatalError("Failed to parse config file: %s", config_path.c_str()); + return nullptr; + } +} + +void ReadConfig(const std::wstring& file_path) { + const auto config = ParseConfig(xe::to_string(file_path)); + for (auto& it : *cvar::ConfigVars) { + auto configVar = static_cast(it.second); + auto configKey = configVar->GetCategory() + "." + configVar->GetName(); + if (config->contains_qualified(configKey)) { + configVar->LoadConfigValue(config->get_qualified(configKey)); + } + } + XELOGI("Loaded config: %S", file_path.c_str()); +} + +void ReadGameConfig(std::wstring file_path) { + const auto config = ParseConfig(xe::to_string(file_path)); + for (auto& it : *cvar::ConfigVars) { + auto configVar = static_cast(it.second); + auto configKey = configVar->GetCategory() + "." + configVar->GetName(); + if (config->contains_qualified(configKey)) { + configVar->LoadGameConfigValue(config->get_qualified(configKey)); + } + } + XELOGI("Loaded game config: %S", file_path.c_str()); +} + +void SaveConfig() { + std::vector vars; + for (const auto& s : *cvar::ConfigVars) vars.push_back(s.second); + std::sort(vars.begin(), vars.end(), sortCvar); + // we use our own write logic because cpptoml doesn't + // allow us to specify comments :( + std::ostringstream output; + std::string lastCategory; + for (auto configVar : vars) { + if (lastCategory != configVar->GetCategory()) { + if (!lastCategory.empty()) { + output << std::endl; + } + lastCategory = configVar->GetCategory(); + output << xe::format_string("[%s]\n", lastCategory.c_str()); + } + output << std::left << std::setw(40) << std::setfill(' ') + << xe::format_string("%s = %s", configVar->GetName().c_str(), + configVar->GetConfigValue().c_str()); + output << xe::format_string("\t# %s\n", + configVar->GetDescription().c_str()); + } + + if (xe::filesystem::PathExists(config_path)) { + std::ifstream existingConfigStream(xe::to_string(config_path).c_str()); + const std::string existingConfig( + (std::istreambuf_iterator(existingConfigStream)), + std::istreambuf_iterator()); + // if the config didn't change, no need to modify the file + if (existingConfig == output.str()) return; + } + + // save the config file + xe::filesystem::CreateParentFolder(config_path); + std::ofstream file; + file.open(xe::to_string(config_path), std::ios::out | std::ios::trunc); + file << output.str(); + file.close(); +} + +void SetupConfig(const std::wstring& config_folder) { + config::config_folder = config_folder; + // check if the user specified a specific config to load + if (!cvars::config.empty()) { + config_path = xe::to_wstring(cvars::config); + if (xe::filesystem::PathExists(config_path)) { + ReadConfig(config_path); + return; + } + } + // if the user specified a --config argument, but the file doesn't exist, + // let's also load the default config + if (!config_folder.empty()) { + config_path = xe::join_paths(config_folder, config_name); + if (xe::filesystem::PathExists(config_path)) { + ReadConfig(config_path); + } + // we only want to save the config if the user is using the default + // config, we don't want to override a user created specific config + SaveConfig(); + } +} + +void LoadGameConfig(const std::wstring& title_id) { + const auto content_folder = xe::join_paths(config_folder, L"content"); + const auto game_folder = xe::join_paths(content_folder, title_id); + const auto game_config_path = xe::join_paths(game_folder, config_name); + if (xe::filesystem::PathExists(game_config_path)) { + ReadGameConfig(game_config_path); + } +} + +} // namespace config diff --git a/src/xenia/config.h b/src/xenia/config.h new file mode 100644 index 000000000..0a1a1ae5f --- /dev/null +++ b/src/xenia/config.h @@ -0,0 +1,10 @@ +#ifndef XENIA_CONFIG_H_ +#define XENIA_CONFIG_H_ +#include + +namespace config { +void SetupConfig(const std::wstring& config_folder); +void LoadGameConfig(const std::wstring& title_id); +} // namespace config + +#endif // XENIA_CONFIG_H_ diff --git a/src/xenia/cpu/backend/x64/premake5.lua b/src/xenia/cpu/backend/x64/premake5.lua index b0d397a2c..ebbc19765 100644 --- a/src/xenia/cpu/backend/x64/premake5.lua +++ b/src/xenia/cpu/backend/x64/premake5.lua @@ -27,6 +27,5 @@ project("xenia-cpu-backend-x64") includedirs({ project_root.."/third_party/capstone/include", - project_root.."/third_party/gflags/src", }) local_platform_files() diff --git a/src/xenia/cpu/backend/x64/x64_backend.cc b/src/xenia/cpu/backend/x64/x64_backend.cc index 27a6ea8f4..26e76bfa0 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.cc +++ b/src/xenia/cpu/backend/x64/x64_backend.cc @@ -28,7 +28,8 @@ DEFINE_bool( enable_haswell_instructions, true, - "Uses the AVX2/FMA/etc instructions on Haswell processors, if available."); + "Uses the AVX2/FMA/etc instructions on Haswell processors, if available.", + "CPU"); namespace xe { namespace cpu { @@ -83,7 +84,7 @@ bool X64Backend::Initialize(Processor* processor) { } // Need movbe to do advanced LOAD/STORE tricks. - if (FLAGS_enable_haswell_instructions) { + if (cvars::enable_haswell_instructions) { machine_info_.supports_extended_load_store = cpu.has(Xbyak::util::Cpu::tMOVBE); } else { diff --git a/src/xenia/cpu/backend/x64/x64_backend.h b/src/xenia/cpu/backend/x64/x64_backend.h index 19c4caab3..432878373 100644 --- a/src/xenia/cpu/backend/x64/x64_backend.h +++ b/src/xenia/cpu/backend/x64/x64_backend.h @@ -10,10 +10,9 @@ #ifndef XENIA_CPU_BACKEND_X64_X64_BACKEND_H_ #define XENIA_CPU_BACKEND_X64_X64_BACKEND_H_ -#include - #include +#include "xenia/base/cvar.h" #include "xenia/cpu/backend/backend.h" DECLARE_bool(enable_haswell_instructions); diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index ef2c8bd57..a66cba0f4 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -9,8 +9,6 @@ #include "xenia/cpu/backend/x64/x64_emitter.h" -#include - #include #include #include @@ -36,11 +34,12 @@ #include "xenia/cpu/thread_state.h" DEFINE_bool(enable_debugprint_log, false, - "Log debugprint traps to the active debugger"); + "Log debugprint traps to the active debugger", "CPU"); DEFINE_bool(ignore_undefined_externs, true, - "Don't exit when an undefined extern is called."); + "Don't exit when an undefined extern is called.", "CPU"); DEFINE_bool(emit_source_annotations, false, - "Add extra movs and nops to make disassembly easier to read."); + "Add extra movs and nops to make disassembly easier to read.", + "CPU"); namespace xe { namespace cpu { @@ -71,7 +70,7 @@ X64Emitter::X64Emitter(X64Backend* backend, XbyakAllocator* allocator) backend_(backend), code_cache_(backend->code_cache()), allocator_(allocator) { - if (FLAGS_enable_haswell_instructions) { + if (cvars::enable_haswell_instructions) { feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tAVX2) ? kX64EmitAVX2 : 0; feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tFMA) ? kX64EmitFMA : 0; feature_flags_ |= cpu_.has(Xbyak::util::Cpu::tLZCNT) ? kX64EmitLZCNT : 0; @@ -245,7 +244,7 @@ bool X64Emitter::Emit(HIRBuilder* builder, size_t* out_stack_size) { add(rsp, (uint32_t)stack_size); ret(); - if (FLAGS_emit_source_annotations) { + if (cvars::emit_source_annotations) { nop(); nop(); nop(); @@ -262,7 +261,7 @@ void X64Emitter::MarkSourceOffset(const Instr* i) { entry->hir_offset = uint32_t(i->block->ordinal << 16) | i->ordinal; entry->code_offset = static_cast(getSize()); - if (FLAGS_emit_source_annotations) { + if (cvars::emit_source_annotations) { nop(); nop(); mov(eax, entry->guest_address); @@ -299,7 +298,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) { // TODO(benvanik): truncate to length? XELOGD("(DebugPrint) %s", str); - if (FLAGS_enable_debugprint_log) { + if (cvars::enable_debugprint_log) { debugging::DebugPrint("(DebugPrint) %s", str); } @@ -309,7 +308,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) { uint64_t TrapDebugBreak(void* raw_context, uint64_t address) { auto thread_state = *reinterpret_cast(raw_context); XELOGE("tw/td forced trap hit! This should be a crash!"); - if (FLAGS_break_on_debugbreak) { + if (cvars::break_on_debugbreak) { xe::debugging::Break(); } return 0; @@ -446,7 +445,7 @@ void X64Emitter::CallIndirect(const hir::Instr* instr, uint64_t UndefinedCallExtern(void* raw_context, uint64_t function_ptr) { auto function = reinterpret_cast(function_ptr); - if (!FLAGS_ignore_undefined_externs) { + if (!cvars::ignore_undefined_externs) { xe::FatalError("undefined extern call to %.8X %s", function->address(), function->name().c_str()); } else { diff --git a/src/xenia/cpu/compiler/passes/conditional_group_pass.cc b/src/xenia/cpu/compiler/passes/conditional_group_pass.cc index ef84991e8..e29eaae45 100644 --- a/src/xenia/cpu/compiler/passes/conditional_group_pass.cc +++ b/src/xenia/cpu/compiler/passes/conditional_group_pass.cc @@ -9,8 +9,6 @@ #include "xenia/cpu/compiler/passes/conditional_group_pass.h" -#include - #include "xenia/base/profiling.h" #include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/ppc/ppc_context.h" diff --git a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc index 3a399cefd..b6b0376fa 100644 --- a/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc +++ b/src/xenia/cpu/compiler/passes/constant_propagation_pass.cc @@ -9,15 +9,16 @@ #include "xenia/cpu/compiler/passes/constant_propagation_pass.h" -#include #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/profiling.h" #include "xenia/cpu/function.h" #include "xenia/cpu/processor.h" -DEFINE_bool(inline_mmio_access, true, "Inline constant MMIO loads and stores."); +DEFINE_bool(inline_mmio_access, true, "Inline constant MMIO loads and stores.", + "CPU"); namespace xe { namespace cpu { @@ -221,7 +222,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder, bool& result) { auto mmio_range = processor_->memory()->LookupVirtualMappedRange(address); - if (FLAGS_inline_mmio_access && mmio_range) { + if (cvars::inline_mmio_access && mmio_range) { i->Replace(&OPCODE_LOAD_MMIO_info, 0); i->src1.offset = reinterpret_cast(mmio_range); i->src2.offset = address; @@ -273,7 +274,7 @@ bool ConstantPropagationPass::Run(HIRBuilder* builder, bool& result) { break; case OPCODE_STORE: case OPCODE_STORE_OFFSET: - if (FLAGS_inline_mmio_access && i->src1.value->IsConstant()) { + if (cvars::inline_mmio_access && i->src1.value->IsConstant()) { auto address = i->src1.value->constant.i32; if (i->opcode->num == OPCODE_STORE_OFFSET) { address += i->src2.value->constant.i32; diff --git a/src/xenia/cpu/compiler/passes/context_promotion_pass.cc b/src/xenia/cpu/compiler/passes/context_promotion_pass.cc index acf3dc584..7b06a6399 100644 --- a/src/xenia/cpu/compiler/passes/context_promotion_pass.cc +++ b/src/xenia/cpu/compiler/passes/context_promotion_pass.cc @@ -9,8 +9,8 @@ #include "xenia/cpu/compiler/passes/context_promotion_pass.h" -#include - +#include "xenia/apu/apu_flags.h" +#include "xenia/base/cvar.h" #include "xenia/base/profiling.h" #include "xenia/cpu/compiler/compiler.h" #include "xenia/cpu/ppc/ppc_context.h" @@ -19,7 +19,7 @@ DECLARE_bool(debug); DEFINE_bool(store_all_context_values, false, - "Don't strip dead context stores to aid in debugging."); + "Don't strip dead context stores to aid in debugging.", "CPU"); namespace xe { namespace cpu { @@ -77,7 +77,7 @@ bool ContextPromotionPass::Run(HIRBuilder* builder) { // Remove all dead stores. // This will break debugging as we can't recover this information when // trying to extract stack traces/register values, so we don't do that. - if (!FLAGS_debug && !FLAGS_store_all_context_values) { + if (!cvars::debug && !cvars::store_all_context_values) { block = builder->first_block(); while (block) { RemoveDeadStoresBlock(block); diff --git a/src/xenia/cpu/cpu_flags.cc b/src/xenia/cpu/cpu_flags.cc index 27de03e08..fab5ef2f0 100644 --- a/src/xenia/cpu/cpu_flags.cc +++ b/src/xenia/cpu/cpu_flags.cc @@ -9,38 +9,42 @@ #include "xenia/cpu/cpu_flags.h" -DEFINE_string(cpu, "any", "CPU backend [any, x64]."); +DEFINE_string(cpu, "any", "CPU backend [any, x64].", "CPU"); DEFINE_string( load_module_map, "", "Loads a .map for symbol names and to diff with the generated symbol " - "database."); + "database.", + "CPU"); DEFINE_bool(disassemble_functions, false, - "Disassemble functions during generation."); + "Disassemble functions during generation.", "CPU"); -DEFINE_bool(trace_functions, false, - "Generate tracing for function statistics."); +DEFINE_bool(trace_functions, false, "Generate tracing for function statistics.", + "CPU"); DEFINE_bool(trace_function_coverage, false, - "Generate tracing for function instruction coverage statistics."); + "Generate tracing for function instruction coverage statistics.", + "CPU"); DEFINE_bool(trace_function_references, false, - "Generate tracing for function address references."); + "Generate tracing for function address references.", "CPU"); DEFINE_bool(trace_function_data, false, - "Generate tracing for function result data."); + "Generate tracing for function result data.", "CPU"); DEFINE_bool( disable_global_lock, false, - "Disables global lock usage in guest code. Does not affect host code."); + "Disables global lock usage in guest code. Does not affect host code.", + "CPU"); DEFINE_bool(validate_hir, false, - "Perform validation checks on the HIR during compilation."); + "Perform validation checks on the HIR during compilation.", "CPU"); // Breakpoints: DEFINE_uint64(break_on_instruction, 0, - "int3 before the given guest address is executed."); -DEFINE_int32(break_condition_gpr, -1, "GPR compared to"); -DEFINE_uint64(break_condition_value, 0, "value compared against"); -DEFINE_string(break_condition_op, "eq", "comparison operator"); -DEFINE_bool(break_condition_truncate, true, "truncate value to 32-bits"); + "int3 before the given guest address is executed.", "CPU"); +DEFINE_int32(break_condition_gpr, -1, "GPR compared to", "CPU"); +DEFINE_uint64(break_condition_value, 0, "value compared against", "CPU"); +DEFINE_string(break_condition_op, "eq", "comparison operator", "CPU"); +DEFINE_bool(break_condition_truncate, true, "truncate value to 32-bits", "CPU"); -DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests."); +DEFINE_bool(break_on_debugbreak, true, "int3 on JITed __debugbreak requests.", + "CPU"); diff --git a/src/xenia/cpu/cpu_flags.h b/src/xenia/cpu/cpu_flags.h index 33b71150e..65a15a87d 100644 --- a/src/xenia/cpu/cpu_flags.h +++ b/src/xenia/cpu/cpu_flags.h @@ -9,8 +9,7 @@ #ifndef XENIA_CPU_CPU_FLAGS_H_ #define XENIA_CPU_CPU_FLAGS_H_ - -#include +#include "xenia/base/cvar.h" DECLARE_string(cpu); diff --git a/src/xenia/cpu/ppc/ppc_emit_control.cc b/src/xenia/cpu/ppc/ppc_emit_control.cc index bdc7dd552..15c990339 100644 --- a/src/xenia/cpu/ppc/ppc_emit_control.cc +++ b/src/xenia/cpu/ppc/ppc_emit_control.cc @@ -728,12 +728,12 @@ int InstrEmit_mtmsr(PPCHIRBuilder& f, const InstrData& i) { f.ZeroExtend(f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE), INT64_TYPE)); if (i.X.RT == 13) { // iff storing from r13 we are taking a lock (disable interrupts). - if (!FLAGS_disable_global_lock) { + if (!cvars::disable_global_lock) { f.CallExtern(f.builtins()->enter_global_lock); } } else { // Otherwise we are restoring interrupts (probably). - if (!FLAGS_disable_global_lock) { + if (!cvars::disable_global_lock) { f.CallExtern(f.builtins()->leave_global_lock); } } @@ -753,12 +753,12 @@ int InstrEmit_mtmsrd(PPCHIRBuilder& f, const InstrData& i) { f.ZeroExtend(f.LoadGPR(i.X.RT), INT64_TYPE)); if (i.X.RT == 13) { // iff storing from r13 we are taking a lock (disable interrupts). - if (!FLAGS_disable_global_lock) { + if (!cvars::disable_global_lock) { f.CallExtern(f.builtins()->enter_global_lock); } } else { // Otherwise we are restoring interrupts (probably). - if (!FLAGS_disable_global_lock) { + if (!cvars::disable_global_lock) { f.CallExtern(f.builtins()->leave_global_lock); } } diff --git a/src/xenia/cpu/ppc/ppc_hir_builder.cc b/src/xenia/cpu/ppc/ppc_hir_builder.cc index 4fdb44e16..284d81c87 100644 --- a/src/xenia/cpu/ppc/ppc_hir_builder.cc +++ b/src/xenia/cpu/ppc/ppc_hir_builder.cc @@ -182,25 +182,25 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) { } void PPCHIRBuilder::MaybeBreakOnInstruction(uint32_t address) { - if (address != FLAGS_break_on_instruction) { + if (address != cvars::break_on_instruction) { return; } Comment("--break-on-instruction target"); - if (FLAGS_break_condition_gpr < 0) { + if (cvars::break_condition_gpr < 0) { DebugBreak(); return; } - auto left = LoadGPR(FLAGS_break_condition_gpr); - auto right = LoadConstantUint64(FLAGS_break_condition_value); - if (FLAGS_break_condition_truncate) { + auto left = LoadGPR(cvars::break_condition_gpr); + auto right = LoadConstantUint64(cvars::break_condition_value); + if (cvars::break_condition_truncate) { left = Truncate(left, INT32_TYPE); right = Truncate(right, INT32_TYPE); } - auto op = FLAGS_break_condition_op.c_str(); + auto op = cvars::break_condition_op.c_str(); // TODO(rick): table? if (strcasecmp(op, "eq") == 0) { TrapTrue(CompareEQ(left, right)); diff --git a/src/xenia/cpu/ppc/ppc_translator.cc b/src/xenia/cpu/ppc/ppc_translator.cc index d408f75b1..94ef275bb 100644 --- a/src/xenia/cpu/ppc/ppc_translator.cc +++ b/src/xenia/cpu/ppc/ppc_translator.cc @@ -9,8 +9,6 @@ #include "xenia/cpu/ppc/ppc_translator.h" -#include - #include "xenia/base/assert.h" #include "xenia/base/byte_order.h" #include "xenia/base/memory.h" @@ -41,7 +39,7 @@ PPCTranslator::PPCTranslator(PPCFrontend* frontend) : frontend_(frontend) { assembler_ = backend->CreateAssembler(); assembler_->Initialize(); - bool validate = FLAGS_validate_hir; + bool validate = cvars::validate_hir; // Merge blocks early. This will let us use more context in other passes. // The CFG is required for simplification and dirtied by it. @@ -108,19 +106,19 @@ bool PPCTranslator::Translate(GuestFunction* function, xe::make_reset_scope(&string_buffer_); // NOTE: we only want to do this when required, as it's expensive to build. - if (FLAGS_disassemble_functions) { + if (cvars::disassemble_functions) { debug_info_flags |= DebugInfoFlags::kDebugInfoAllDisasm; } - if (FLAGS_trace_functions) { + if (cvars::trace_functions) { debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctions; } - if (FLAGS_trace_function_coverage) { + if (cvars::trace_function_coverage) { debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionCoverage; } - if (FLAGS_trace_function_references) { + if (cvars::trace_function_references) { debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionReferences; } - if (FLAGS_trace_function_data) { + if (cvars::trace_function_data) { debug_info_flags |= DebugInfoFlags::kDebugInfoTraceFunctionData; } std::unique_ptr debug_info; diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc index bd2652c20..17304124f 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_main.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" @@ -26,9 +24,9 @@ #endif // XE_COMPILER_MSVC DEFINE_string(test_path, "src/xenia/cpu/ppc/testing/", - "Directory scanned for test files."); + "Directory scanned for test files.", "Other"); DEFINE_string(test_bin_path, "src/xenia/cpu/ppc/testing/bin/", - "Directory with binary outputs of the test files."); + "Directory with binary outputs of the test files.", "Other"); namespace xe { namespace cpu { @@ -54,8 +52,8 @@ class TestSuite { name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) + 1); name = ReplaceExtension(name, L""); - map_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".map"; - bin_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".bin"; + map_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".map"; + bin_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".bin"; } bool Load() { @@ -192,11 +190,11 @@ class TestRunner { std::unique_ptr backend; if (!backend) { #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "x64") { + if (cvars::cpu == "x64") { backend.reset(new xe::cpu::backend::x64::X64Backend()); } #endif // XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "any") { + if (cvars::cpu == "any") { #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND if (!backend) { backend.reset(new xe::cpu::backend::x64::X64Backend()); @@ -408,7 +406,7 @@ bool RunTests(const std::wstring& test_name) { int passed_count = 0; auto test_path_root = - xe::fix_path_separators(xe::to_wstring(FLAGS_test_path)); + xe::fix_path_separators(xe::to_wstring(cvars::test_path)); std::vector test_files; if (!DiscoverTests(test_path_root, test_files)) { return false; diff --git a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc index 25934f252..61d38412d 100644 --- a/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc +++ b/src/xenia/cpu/ppc/testing/ppc_testing_native_main.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include "xenia/base/filesystem.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" @@ -58,8 +56,8 @@ class TestSuite { name = src_file_path.substr(src_file_path.find_last_of(xe::kPathSeparator) + 1); name = ReplaceExtension(name, L""); - map_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".map"; - bin_file_path = xe::to_wstring(FLAGS_test_bin_path) + name + L".bin"; + map_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".map"; + bin_file_path = xe::to_wstring(cvars::test_bin_path) + name + L".bin"; } bool Load() { @@ -454,7 +452,7 @@ bool RunTests(const std::wstring& test_name) { int passed_count = 0; auto test_path_root = - xe::fix_path_separators(xe::to_wstring(FLAGS_test_path)); + xe::fix_path_separators(xe::to_wstring(cvars::test_path)); std::vector test_files; if (!DiscoverTests(test_path_root, test_files)) { return false; diff --git a/src/xenia/cpu/ppc/testing/premake5.lua b/src/xenia/cpu/ppc/testing/premake5.lua index d2d5549cd..e318d8db5 100644 --- a/src/xenia/cpu/ppc/testing/premake5.lua +++ b/src/xenia/cpu/ppc/testing/premake5.lua @@ -11,7 +11,6 @@ project("xenia-cpu-ppc-tests") "xenia-cpu-backend-x64", "xenia-cpu", "xenia-base", - "gflags", "capstone", -- cpu-backend-x64 "mspack", }) @@ -22,15 +21,11 @@ project("xenia-cpu-ppc-tests") files({ "*.s", }) - includedirs({ - project_root.."/third_party/gflags/src", - }) filter("files:*.s") flags({"ExcludeFromBuild"}) filter("platforms:Windows") debugdir(project_root) debugargs({ - "--flagfile=scratch/flags.txt", "2>&1", "1>scratch/stdout-testing.txt", }) @@ -46,7 +41,6 @@ project("xenia-cpu-ppc-nativetests") language("C++") links({ "xenia-base", - "gflags", }) files({ "ppc_testing_native_main.cc", @@ -59,9 +53,6 @@ project("xenia-cpu-ppc-nativetests") filter("files:instr_*.s", "files:seq_*.s") flags({"ExcludeFromBuild"}) filter({}) - includedirs({ - project_root.."/third_party/gflags/src", - }) buildoptions({ "-Wa,-mregnames", -- Tell GAS to accept register names. }) diff --git a/src/xenia/cpu/premake5.lua b/src/xenia/cpu/premake5.lua index 96a41f6e0..748602659 100644 --- a/src/xenia/cpu/premake5.lua +++ b/src/xenia/cpu/premake5.lua @@ -12,7 +12,6 @@ project("xenia-cpu") }) includedirs({ project_root.."/third_party/llvm/include", - project_root.."/third_party/gflags/src", }) local_platform_files() local_platform_files("backend") diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 8088e4bb1..278c60de8 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -9,12 +9,11 @@ #include "xenia/cpu/processor.h" -#include - #include "xenia/base/assert.h" #include "xenia/base/atomic.h" #include "xenia/base/byte_order.h" #include "xenia/base/byte_stream.h" +#include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/exception_handler.h" #include "xenia/base/logging.h" @@ -42,9 +41,11 @@ #endif DEFINE_bool(debug, DEFAULT_DEBUG_FLAG, - "Allow debugging and retain debug information."); -DEFINE_string(trace_function_data_path, "", "File to write trace data to."); -DEFINE_bool(break_on_start, false, "Break into the debugger on startup."); + "Allow debugging and retain debug information.", "General"); +DEFINE_string(trace_function_data_path, "", "File to write trace data to.", + "CPU"); +DEFINE_bool(break_on_start, false, "Break into the debugger on startup.", + "CPU"); namespace xe { namespace kernel { @@ -132,14 +133,14 @@ bool Processor::Setup(std::unique_ptr backend) { stack_walker_ = StackWalker::Create(backend_->code_cache()); if (!stack_walker_) { // TODO(benvanik): disable features. - if (FLAGS_debug) { + if (cvars::debug) { XELOGW("Disabling --debug due to lack of stack walker"); - FLAGS_debug = false; + cvars::debug = false; } } // Open the trace data path, if requested. - functions_trace_path_ = xe::to_wstring(FLAGS_trace_function_data_path); + functions_trace_path_ = xe::to_wstring(cvars::trace_function_data_path); if (!functions_trace_path_.empty()) { functions_trace_file_ = ChunkedMappedMemoryWriter::Open( functions_trace_path_, 32 * 1024 * 1024, true); @@ -149,7 +150,7 @@ bool Processor::Setup(std::unique_ptr backend) { } void Processor::PreLaunch() { - if (FLAGS_break_on_start) { + if (cvars::break_on_start) { // Start paused. XELOGI("Breaking into debugger because of --break_on_start..."); execution_state_ = ExecutionState::kRunning; @@ -629,9 +630,9 @@ bool Processor::OnThreadBreakpointHit(Exception* ex) { SuspendAllBreakpoints(); } - // Update all thread states with their latest values, using the context we got - // from the exception instead of a sampled value (as it would just show the - // exception handler). + // Update all thread states with their latest values, using the context we + // got from the exception instead of a sampled value (as it would just show + // the exception handler). UpdateThreadExecutionStates(thread_info->thread_id, ex->thread_context()); // Walk the captured thread stack and look for breakpoints at any address in diff --git a/src/xenia/cpu/processor.h b/src/xenia/cpu/processor.h index 57f714593..bb8709a72 100644 --- a/src/xenia/cpu/processor.h +++ b/src/xenia/cpu/processor.h @@ -10,13 +10,12 @@ #ifndef XENIA_CPU_PROCESSOR_H_ #define XENIA_CPU_PROCESSOR_H_ -#include - #include #include #include #include +#include "xenia/base/cvar.h" #include "xenia/base/mapped_memory.h" #include "xenia/base/mutex.h" #include "xenia/cpu/backend/backend.h" diff --git a/src/xenia/cpu/stack_walker_win.cc b/src/xenia/cpu/stack_walker_win.cc index 9ff6b220c..4339e3a8b 100644 --- a/src/xenia/cpu/stack_walker_win.cc +++ b/src/xenia/cpu/stack_walker_win.cc @@ -9,8 +9,6 @@ #include "xenia/cpu/stack_walker.h" -#include - #include #include "xenia/base/logging.h" @@ -20,7 +18,7 @@ #include "xenia/cpu/processor.h" DEFINE_bool(debug_symbol_loader, false, - "Enable dbghelp debug logging and validation."); + "Enable dbghelp debug logging and validation.", "CPU"); // Must be included after platform_win.h: #pragma warning(push) @@ -98,7 +96,7 @@ bool InitializeStackWalker() { // Initialize the symbol lookup services. DWORD options = sym_get_options_(); - if (FLAGS_debug_symbol_loader) { + if (cvars::debug_symbol_loader) { options |= SYMOPT_DEBUG; } options |= SYMOPT_DEFERRED_LOADS; diff --git a/src/xenia/cpu/testing/premake5.lua b/src/xenia/cpu/testing/premake5.lua index 30e60604f..a3c2b8566 100644 --- a/src/xenia/cpu/testing/premake5.lua +++ b/src/xenia/cpu/testing/premake5.lua @@ -2,9 +2,6 @@ project_root = "../../../.." include(project_root.."/tools/build") test_suite("xenia-cpu-tests", project_root, ".", { - includedirs = { - project_root.."/third_party/gflags/src", - }, links = { "capstone", "xenia-base", diff --git a/src/xenia/cpu/testing/sandbox_main.cc b/src/xenia/cpu/testing/sandbox_main.cc index 9aedbf288..0998ddefe 100644 --- a/src/xenia/cpu/testing/sandbox_main.cc +++ b/src/xenia/cpu/testing/sandbox_main.cc @@ -14,8 +14,6 @@ #include "xenia/cpu/ppc/ppc_frontend.h" #include "xenia/cpu/raw_module.h" -#include - namespace xe { namespace cpu { namespace sandbox { diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 8f9e0be21..3b6475362 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -1008,8 +1008,8 @@ bool XexModule::LoadContinue() { } // Load a specified module map and diff. - if (FLAGS_load_module_map.size()) { - if (!ReadMap(FLAGS_load_module_map.c_str())) { + if (cvars::load_module_map.size()) { + if (!ReadMap(cvars::load_module_map.c_str())) { return false; } } diff --git a/src/xenia/debug/ui/debug_window.cc b/src/xenia/debug/ui/debug_window.cc index 0e74a1670..98bc5bd80 100644 --- a/src/xenia/debug/ui/debug_window.cc +++ b/src/xenia/debug/ui/debug_window.cc @@ -9,8 +9,6 @@ #include "xenia/debug/ui/debug_window.h" -#include - #include #include #include @@ -35,7 +33,7 @@ #include "xenia/ui/graphics_provider.h" #include "xenia/ui/imgui_drawer.h" -DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools."); +DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.", "Other"); namespace xe { namespace debug { @@ -238,7 +236,7 @@ void DebugWindow::DrawFrame() { ImGui::End(); ImGui::PopStyleVar(); - if (FLAGS_imgui_debug) { + if (cvars::imgui_debug) { ImGui::ShowTestWindow(); ImGui::ShowMetricsWindow(); } diff --git a/src/xenia/debug/ui/premake5.lua b/src/xenia/debug/ui/premake5.lua index e631f7f5b..84ca9bbd8 100644 --- a/src/xenia/debug/ui/premake5.lua +++ b/src/xenia/debug/ui/premake5.lua @@ -16,7 +16,6 @@ project("xenia-debug-ui") defines({ }) includedirs({ - project_root.."/third_party/gflags/src", project_root.."/third_party/yaml-cpp/include/", }) local_platform_files() diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 81fe5cf57..3a92ae99d 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -9,13 +9,14 @@ #include "xenia/emulator.h" -#include #include +#include "config.h" #include "xenia/apu/audio_system.h" #include "xenia/base/assert.h" #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" +#include "xenia/base/cvar.h" #include "xenia/base/debugging.h" #include "xenia/base/exception_handler.h" #include "xenia/base/logging.h" @@ -44,7 +45,8 @@ #include "xenia/vfs/virtual_file_system.h" DEFINE_double(time_scalar, 1.0, - "Scalar used to speed or slow time (1x, 2x, 1/2x, etc)."); + "Scalar used to speed or slow time (1x, 2x, 1/2x, etc).", + "General"); namespace xe { @@ -112,7 +114,7 @@ X_STATUS Emulator::Setup( // We could reset this with save state data/constant value to help replays. Clock::set_guest_system_time_base(Clock::QueryHostSystemTime()); // This can be adjusted dynamically, as well. - Clock::set_guest_time_scalar(FLAGS_time_scalar); + Clock::set_guest_time_scalar(cvars::time_scalar); // Before we can set thread affinity we must enable the process to use all // logical processors. @@ -130,11 +132,11 @@ X_STATUS Emulator::Setup( std::unique_ptr backend; if (!backend) { #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "x64") { + if (cvars::cpu == "x64") { backend.reset(new xe::cpu::backend::x64::X64Backend()); } #endif // XENIA_HAS_X64_BACKEND - if (FLAGS_cpu == "any") { + if (cvars::cpu == "any") { #if defined(XENIA_HAS_X64_BACKEND) && XENIA_HAS_X64_BACKEND if (!backend) { backend.reset(new xe::cpu::backend::x64::X64Backend()); @@ -646,6 +648,7 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path, if (module->title_id()) { char title_id[9] = {0}; std::snprintf(title_id, xe::countof(title_id), "%08X", module->title_id()); + config::LoadGameConfig(xe::to_wstring(title_id)); uint32_t resource_data = 0; uint32_t resource_size = 0; if (XSUCCEEDED( diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 1f7e36748..ff7b00521 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -393,7 +393,7 @@ void CommandProcessor::IssueSwap(uint32_t frontbuffer_ptr, // This prevents the display from pulling the backbuffer out from under us. // If we skip a lot then we may need to buffer more, but as the display // thread should be fairly idle that shouldn't happen. - if (!FLAGS_vsync) { + if (!cvars::vsync) { std::lock_guard lock(swap_state_.mutex); if (swap_state_.pending) { swap_state_.pending = false; @@ -895,7 +895,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingBuffer* reader, // Wait. if (wait >= 0x100) { PrepareForWait(); - if (!FLAGS_vsync) { + if (!cvars::vsync) { // User wants it fast and dangerous. xe::threading::MaybeYield(); } else { diff --git a/src/xenia/gpu/d3d12/d3d12_command_processor.cc b/src/xenia/gpu/d3d12/d3d12_command_processor.cc index 30b7f2cd7..c0f57485c 100644 --- a/src/xenia/gpu/d3d12/d3d12_command_processor.cc +++ b/src/xenia/gpu/d3d12/d3d12_command_processor.cc @@ -7,18 +7,17 @@ ****************************************************************************** */ -#include "xenia/gpu/d3d12/d3d12_command_processor.h" - -#include #include "third_party/xxhash/xxhash.h" #include #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/profiling.h" +#include "xenia/gpu/d3d12/d3d12_command_processor.h" #include "xenia/gpu/d3d12/d3d12_graphics_system.h" #include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/xenos.h" @@ -26,27 +25,31 @@ DEFINE_bool(d3d12_edram_rov, true, "Use rasterizer-ordered views for render target emulation where " - "available."); + "available.", + "D3D12"); // Some games (such as Banjo-Kazooie) are not aware of the half-pixel offset and // may be blurry or have texture sampling artifacts, in this case the user may // disable half-pixel offset by setting this to false. DEFINE_bool(d3d12_half_pixel_offset, true, - "Enable half-pixel vertex and VPOS offset."); + "Enable half-pixel vertex and VPOS offset.", "D3D12"); DEFINE_bool(d3d12_readback_memexport, false, "Read data written by memory export in shaders on the CPU. This " "may be needed in some games (but many only access exported data " "on the GPU, and this flag isn't needed to handle such behavior), " "but causes mid-frame synchronization, so it has a huge " - "performance impact."); + "performance impact.", + "D3D12"); DEFINE_bool(d3d12_readback_resolve, false, "Read render-to-texture results on the CPU. This may be needed in " "some games, for instance, for screenshots in saved games, but " "causes mid-frame synchronization, so it has a huge performance " - "impact."); + "impact.", + "D3D12"); DEFINE_bool(d3d12_ssaa_custom_sample_positions, false, "Enable custom SSAA sample positions for the RTV/DSV rendering " "path where available instead of centers (experimental, not very " - "high-quality)."); + "high-quality).", + "D3D12"); namespace xe { namespace gpu { @@ -78,7 +81,7 @@ void D3D12CommandProcessor::RequestFrameTrace(const std::wstring& root_path) { } bool D3D12CommandProcessor::IsROVUsedForEDRAM() const { - if (!FLAGS_d3d12_edram_rov) { + if (!cvars::d3d12_edram_rov) { return false; } auto provider = GetD3D12Context()->GetD3D12Provider(); @@ -540,7 +543,7 @@ void D3D12CommandProcessor::SetSamplePositions(MsaaSamples sample_positions) { // for ROV output. There's hardly any difference between 2,6 (of 0 and 3 with // 4x MSAA) and 4,4 anyway. // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/nf-d3d12-id3d12graphicscommandlist1-setsamplepositions - if (FLAGS_d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) { + if (cvars::d3d12_ssaa_custom_sample_positions && !IsROVUsedForEDRAM()) { auto provider = GetD3D12Context()->GetD3D12Provider(); auto tier = provider->GetProgrammableSamplePositionsTier(); if (tier >= 2 && @@ -1611,7 +1614,7 @@ bool D3D12CommandProcessor::IssueDraw(PrimitiveType primitive_type, memexport_range.base_address_dwords << 2, memexport_range.size_dwords << 2); } - if (FLAGS_d3d12_readback_memexport) { + if (cvars::d3d12_readback_memexport) { // Read the exported data on the CPU. uint32_t memexport_total_size = 0; for (uint32_t i = 0; i < memexport_range_count; ++i) { @@ -1672,7 +1675,7 @@ bool D3D12CommandProcessor::IssueCopy() { written_length)) { return false; } - if (FLAGS_d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() && + if (cvars::d3d12_readback_resolve && !texture_cache_->IsResolutionScale2X() && written_length) { // Read the resolved data on the CPU. ID3D12Resource* readback_buffer = RequestReadbackBuffer(written_length); @@ -2274,7 +2277,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( // TODO(Triang3l): Check if ps_param_gen should give center positions in // OpenGL mode on the Xbox 360. float pixel_half_pixel_offset = 0.5f; - if (FLAGS_d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) { + if (cvars::d3d12_half_pixel_offset && !(pa_su_vtx_cntl & (1 << 0))) { // Signs are hopefully correct here, tested in GTA IV on both clearing // (without a viewport) and drawing things near the edges of the screen. if (pa_cl_vte_cntl & (1 << 0)) { @@ -2406,7 +2409,7 @@ void D3D12CommandProcessor::UpdateSystemConstantValues( // be incorrect in this case, but there's no other way without using ROV, // though there's an option to limit the range to -1...1). // http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf - if (!IsROVUsedForEDRAM() && FLAGS_d3d12_16bit_rtv_full_range) { + if (!IsROVUsedForEDRAM() && cvars::d3d12_16bit_rtv_full_range) { color_exp_bias -= 5; } } diff --git a/src/xenia/gpu/d3d12/pipeline_cache.cc b/src/xenia/gpu/d3d12/pipeline_cache.cc index 44fb45f66..89286be18 100644 --- a/src/xenia/gpu/d3d12/pipeline_cache.cc +++ b/src/xenia/gpu/d3d12/pipeline_cache.cc @@ -9,8 +9,6 @@ #include "xenia/gpu/d3d12/pipeline_cache.h" -#include - #include #include #include @@ -20,6 +18,7 @@ #include "third_party/xxhash/xxhash.h" #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/profiling.h" @@ -28,21 +27,24 @@ #include "xenia/gpu/gpu_flags.h" DEFINE_bool(d3d12_dxbc_disasm, false, - "Disassemble DXBC shaders after generation."); + "Disassemble DXBC shaders after generation.", "D3D12"); DEFINE_int32( d3d12_pipeline_creation_threads, -1, "Number of threads used for graphics pipeline state creation. -1 to " "calculate automatically (75% of logical CPU cores), 1-16 to specify the " "number of threads explicitly, 0 to disable multithreaded pipeline state " - "creation."); + "creation.", + "D3D12"); DEFINE_bool( d3d12_tessellation_adaptive, false, "Allow games to use adaptive tessellation - may be disabled if the game " "has issues with memexport, the maximum factor will be used in this case. " "Temporarily disabled by default since there are visible cracks currently " - "in Halo 3."); + "in Halo 3.", + "D3D12"); DEFINE_bool(d3d12_tessellation_wireframe, false, - "Display tessellated surfaces as wireframe for debugging."); + "Display tessellated surfaces as wireframe for debugging.", + "D3D12"); namespace xe { namespace gpu { @@ -81,18 +83,18 @@ PipelineCache::PipelineCache(D3D12CommandProcessor* command_processor, PipelineCache::~PipelineCache() { Shutdown(); } bool PipelineCache::Initialize() { - if (FLAGS_d3d12_pipeline_creation_threads != 0) { + if (cvars::d3d12_pipeline_creation_threads != 0) { creation_threads_busy_ = 0; creation_completion_event_ = xe::threading::Event::CreateManualResetEvent(true); creation_completion_set_event_ = false; creation_threads_shutdown_ = false; uint32_t creation_thread_count; - if (FLAGS_d3d12_pipeline_creation_threads < 0) { + if (cvars::d3d12_pipeline_creation_threads < 0) { creation_thread_count = std::max( xe::threading::logical_processor_count() * 3 / 4, uint32_t(1)); } else { - creation_thread_count = uint32_t(FLAGS_d3d12_pipeline_creation_threads); + creation_thread_count = uint32_t(cvars::d3d12_pipeline_creation_threads); } creation_thread_count = std::min(creation_thread_count, uint32_t(16)); for (uint32_t i = 0; i < creation_thread_count; ++i) { @@ -331,7 +333,7 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader, } // Disassemble the shader for dumping. - if (FLAGS_d3d12_dxbc_disasm) { + if (cvars::d3d12_dxbc_disasm) { auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); if (!shader->DisassembleDxbc(provider)) { XELOGE("Failed to disassemble DXBC shader %.16" PRIX64, @@ -340,8 +342,8 @@ bool PipelineCache::TranslateShader(D3D12Shader* shader, } // Dump shader files if desired. - if (!FLAGS_dump_shaders.empty()) { - shader->Dump(FLAGS_dump_shaders, "d3d12"); + if (!cvars::dump_shaders.empty()) { + shader->Dump(cvars::dump_shaders, "d3d12"); } return shader->is_valid(); @@ -390,7 +392,7 @@ bool PipelineCache::GetCurrentStateDescription( break; case TessellationMode::kAdaptive: description_out.tessellation_mode = - FLAGS_d3d12_tessellation_adaptive + cvars::d3d12_tessellation_adaptive ? PipelineTessellationMode::kAdaptive : PipelineTessellationMode::kContinuous; break; @@ -549,7 +551,7 @@ bool PipelineCache::GetCurrentStateDescription( description_out.depth_bias_slope_scaled = poly_offset_scale * (1.0f / 16.0f); } - if (FLAGS_d3d12_tessellation_wireframe && tessellated && + if (cvars::d3d12_tessellation_wireframe && tessellated && (primitive_type == PrimitiveType::kTrianglePatch || primitive_type == PrimitiveType::kQuadPatch)) { description_out.fill_mode_wireframe = 1; diff --git a/src/xenia/gpu/d3d12/primitive_converter.cc b/src/xenia/gpu/d3d12/primitive_converter.cc index 33e281680..0da7e33d0 100644 --- a/src/xenia/gpu/d3d12/primitive_converter.cc +++ b/src/xenia/gpu/d3d12/primitive_converter.cc @@ -9,11 +9,10 @@ #include "xenia/gpu/d3d12/primitive_converter.h" -#include - #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -26,7 +25,8 @@ DEFINE_bool(d3d12_convert_quads_to_triangles, false, "Convert quad lists to triangle lists on the CPU instead of using " "a geometry shader. Not recommended for playing, for debugging " "primarily (because PIX fails to display vertices when a geometry " - "shader is used)."); + "shader is used).", + "D3D12"); namespace xe { namespace gpu { @@ -176,7 +176,7 @@ PrimitiveType PrimitiveConverter::GetReplacementPrimitiveType( case PrimitiveType::kLineLoop: return PrimitiveType::kLineStrip; case PrimitiveType::kQuadList: - if (FLAGS_d3d12_convert_quads_to_triangles) { + if (cvars::d3d12_convert_quads_to_triangles) { return PrimitiveType::kTriangleList; } break; @@ -213,7 +213,7 @@ PrimitiveConverter::ConversionResult PrimitiveConverter::ConvertPrimitives( return ConversionResult::kConversionNotNeeded; } } else if (source_type == PrimitiveType::kQuadList) { - if (!FLAGS_d3d12_convert_quads_to_triangles) { + if (!cvars::d3d12_convert_quads_to_triangles) { return ConversionResult::kConversionNotNeeded; } } else if (source_type != PrimitiveType::kTriangleFan && @@ -731,7 +731,7 @@ D3D12_GPU_VIRTUAL_ADDRESS PrimitiveConverter::GetStaticIndexBuffer( kStaticIBTriangleFanOffset * sizeof(uint16_t); } if (source_type == PrimitiveType::kQuadList && - FLAGS_d3d12_convert_quads_to_triangles) { + cvars::d3d12_convert_quads_to_triangles) { index_count_out = (index_count >> 2) * 6; return static_ib_gpu_address_ + kStaticIBQuadOffset * sizeof(uint16_t); } diff --git a/src/xenia/gpu/d3d12/render_target_cache.cc b/src/xenia/gpu/d3d12/render_target_cache.cc index 12081e84a..a006fe113 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.cc +++ b/src/xenia/gpu/d3d12/render_target_cache.cc @@ -9,13 +9,12 @@ #include "xenia/gpu/d3d12/render_target_cache.h" -#include - #include #include #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -27,12 +26,14 @@ DEFINE_bool(d3d12_16bit_rtv_full_range, true, "Use full -32...32 range for RG16 and RGBA16 render targets " - "(at the expense of blending correctness) without ROV."); + "(at the expense of blending correctness) without ROV.", + "D3D12"); DEFINE_bool(d3d12_resolution_scale_resolve_edge_clamp, true, "When using resolution scale, apply the hack that duplicates the " "right/lower subpixel in the left and top sides of render target " "resolve areas to eliminate the gap caused by half-pixel offset " - "(this is necessary for certain games like GTA IV to work)."); + "(this is necessary for certain games like GTA IV to work).", + "D3D12"); DECLARE_bool(d3d12_half_pixel_offset); namespace xe { @@ -1303,7 +1304,7 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, // there on the guest side. // http://www.students.science.uu.nl/~3220516/advancedgraphics/papers/inferred_lighting.pdf if (command_processor_->IsROVUsedForEDRAM() || - FLAGS_d3d12_16bit_rtv_full_range) { + cvars::d3d12_16bit_rtv_full_range) { dest_exp_bias += 5; } } @@ -1340,8 +1341,9 @@ bool RenderTargetCache::ResolveCopy(SharedMemory* shared_memory, // sides of the screen caused by half-pixel offset becoming whole pixel offset // with scaled rendering resolution. bool resolution_scale_edge_clamp = - resolution_scale_2x_ && FLAGS_d3d12_resolution_scale_resolve_edge_clamp && - FLAGS_d3d12_half_pixel_offset && + resolution_scale_2x_ && + cvars::d3d12_resolution_scale_resolve_edge_clamp && + cvars::d3d12_half_pixel_offset && !(regs[XE_GPU_REG_PA_SU_VTX_CNTL].u32 & 0x1); if (sample_select <= xenos::CopySampleSelect::k3 && src_texture_format == dest_format && dest_exp_bias == 0) { diff --git a/src/xenia/gpu/d3d12/render_target_cache.h b/src/xenia/gpu/d3d12/render_target_cache.h index dd1d4999f..0ccf8be0b 100644 --- a/src/xenia/gpu/d3d12/render_target_cache.h +++ b/src/xenia/gpu/d3d12/render_target_cache.h @@ -10,10 +10,9 @@ #ifndef XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_ #define XENIA_GPU_D3D12_RENDER_TARGET_CACHE_H_ -#include - #include +#include "xenia/base/cvar.h" #include "xenia/gpu/d3d12/d3d12_shader.h" #include "xenia/gpu/d3d12/shared_memory.h" #include "xenia/gpu/d3d12/texture_cache.h" diff --git a/src/xenia/gpu/d3d12/shared_memory.cc b/src/xenia/gpu/d3d12/shared_memory.cc index 8b74daebe..c4c523eff 100644 --- a/src/xenia/gpu/d3d12/shared_memory.cc +++ b/src/xenia/gpu/d3d12/shared_memory.cc @@ -9,12 +9,11 @@ #include "xenia/gpu/d3d12/shared_memory.h" -#include - #include #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/memory.h" @@ -26,7 +25,8 @@ DEFINE_bool(d3d12_tiled_shared_memory, true, "Enable tiled resources for shared memory emulation. Disabling " "them greatly increases video memory usage - a 512 MB buffer is " "created - but allows graphics debuggers that don't support tiled " - "resources to work."); + "resources to work.", + "D3D12"); namespace xe { namespace gpu { @@ -453,7 +453,7 @@ void SharedMemory::RangeWrittenByGPU(uint32_t start, uint32_t length) { } bool SharedMemory::AreTiledResourcesUsed() const { - if (!FLAGS_d3d12_tiled_shared_memory) { + if (!cvars::d3d12_tiled_shared_memory) { return false; } auto provider = command_processor_->GetD3D12Context()->GetD3D12Provider(); diff --git a/src/xenia/gpu/d3d12/texture_cache.cc b/src/xenia/gpu/d3d12/texture_cache.cc index 9690abc05..1fb339b9a 100644 --- a/src/xenia/gpu/d3d12/texture_cache.cc +++ b/src/xenia/gpu/d3d12/texture_cache.cc @@ -9,7 +9,6 @@ #include "xenia/gpu/d3d12/texture_cache.h" -#include #include "third_party/xxhash/xxhash.h" #include @@ -17,6 +16,7 @@ #include "xenia/base/assert.h" #include "xenia/base/clock.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/profiling.h" @@ -27,20 +27,24 @@ DEFINE_int32(d3d12_resolution_scale, 1, "Scale of rendering width and height (currently only 1 and 2 " - "are available)."); + "are available).", + "D3D12"); DEFINE_int32(d3d12_texture_cache_limit_soft, 384, "Maximum host texture memory usage (in megabytes) above which old " "textures will be destroyed (lifetime configured with " "d3d12_texture_cache_limit_soft_lifetime). If using 2x resolution " - "scale, 1.25x of this is used."); + "scale, 1.25x of this is used.", + "D3D12"); DEFINE_int32(d3d12_texture_cache_limit_soft_lifetime, 30, "Seconds a texture should be unused to be considered old enough " "to be deleted if texture memory usage exceeds " - "d3d12_texture_cache_limit_soft."); + "d3d12_texture_cache_limit_soft.", + "D3D12"); DEFINE_int32(d3d12_texture_cache_limit_hard, 768, "Maximum host texture memory usage (in megabytes) above which " "textures will be destroyed as soon as possible. If using 2x " - "resolution scale, 1.25x of this is used."); + "resolution scale, 1.25x of this is used.", + "D3D12"); namespace xe { namespace gpu { @@ -484,7 +488,7 @@ bool TextureCache::Initialize() { // Try to create the tiled buffer 2x resolution scaling. // Not currently supported with the RTV/DSV output path for various reasons. // As of November 27th, 2018, PIX doesn't support tiled buffers. - if (FLAGS_d3d12_resolution_scale >= 2 && + if (cvars::d3d12_resolution_scale >= 2 && command_processor_->IsROVUsedForEDRAM() && provider->GetTiledResourcesTier() >= 1 && provider->GetGraphicsAnalysis() == nullptr && @@ -738,14 +742,14 @@ void TextureCache::BeginFrame() { // If memory usage is too high, destroy unused textures. uint64_t last_completed_frame = command_processor_->GetD3D12Context()->GetLastCompletedFrame(); - uint32_t limit_soft_mb = FLAGS_d3d12_texture_cache_limit_soft; - uint32_t limit_hard_mb = FLAGS_d3d12_texture_cache_limit_hard; + uint32_t limit_soft_mb = cvars::d3d12_texture_cache_limit_soft; + uint32_t limit_hard_mb = cvars::d3d12_texture_cache_limit_hard; if (IsResolutionScale2X()) { limit_soft_mb += limit_soft_mb >> 2; limit_hard_mb += limit_hard_mb >> 2; } uint32_t limit_soft_lifetime = - std::max(FLAGS_d3d12_texture_cache_limit_soft_lifetime, 0) * 1000; + std::max(cvars::d3d12_texture_cache_limit_soft_lifetime, 0) * 1000; bool destroyed_any = false; while (texture_used_first_ != nullptr) { uint64_t total_size_mb = textures_total_size_ >> 20; diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index f50e4bf7b..5e785bf6e 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -9,8 +9,6 @@ #include "xenia/gpu/dxbc_shader_translator.h" -#include - #include #include #include @@ -19,6 +17,7 @@ #include "third_party/dxbc/d3d12TokenizedProgramFormat.hpp" #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" DEFINE_bool(dxbc_switch, true, "Use switch rather than if for flow control. Turning this off or " @@ -27,10 +26,12 @@ DEFINE_bool(dxbc_switch, true, "Halo 3 appears to crash when if is used for flow control " "(possibly the shader compiler tries to flatten them). On Intel " "HD Graphics, this is ignored because of a crash with the switch " - "instruction."); + "instruction.", + "D3D12"); DEFINE_bool(dxbc_source_map, false, "Disassemble Xenos instructions as comments in the resulting DXBC " - "for debugging."); + "for debugging.", + "D3D12"); namespace xe { namespace gpu { @@ -182,7 +183,7 @@ void DxbcShaderTranslator::Reset() { bool DxbcShaderTranslator::UseSwitchForControlFlow() const { // Xenia crashes on Intel HD Graphics 4000 with switch. - return FLAGS_dxbc_switch && vendor_id_ != 0x8086; + return cvars::dxbc_switch && vendor_id_ != 0x8086; } uint32_t DxbcShaderTranslator::PushSystemTemp(uint32_t zero_mask, @@ -1861,7 +1862,7 @@ std::vector DxbcShaderTranslator::CompleteTranslation() { } void DxbcShaderTranslator::EmitInstructionDisassembly() { - if (!FLAGS_dxbc_source_map) { + if (!cvars::dxbc_source_map) { return; } @@ -3019,7 +3020,7 @@ void DxbcShaderTranslator::ProcessLabel(uint32_t cf_index) { void DxbcShaderTranslator::ProcessExecInstructionBegin( const ParsedExecInstruction& instr) { - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); // Will be emitted by UpdateExecConditionals. @@ -3070,7 +3071,7 @@ void DxbcShaderTranslator::ProcessLoopStartInstruction( // Loop control is outside execs - actually close the last exec. CloseExecConditionals(); - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); EmitInstructionDisassembly(); @@ -3182,7 +3183,7 @@ void DxbcShaderTranslator::ProcessLoopEndInstruction( // Loop control is outside execs - actually close the last exec. CloseExecConditionals(); - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); EmitInstructionDisassembly(); @@ -3340,7 +3341,7 @@ void DxbcShaderTranslator::ProcessLoopEndInstruction( void DxbcShaderTranslator::ProcessJumpInstruction( const ParsedJumpInstruction& instr) { - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); // Will be emitted by UpdateExecConditionals. @@ -3369,7 +3370,7 @@ void DxbcShaderTranslator::ProcessJumpInstruction( void DxbcShaderTranslator::ProcessAllocInstruction( const ParsedAllocInstruction& instr) { - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); EmitInstructionDisassembly(); diff --git a/src/xenia/gpu/dxbc_shader_translator.h b/src/xenia/gpu/dxbc_shader_translator.h index 5c9cb7af3..73451422f 100644 --- a/src/xenia/gpu/dxbc_shader_translator.h +++ b/src/xenia/gpu/dxbc_shader_translator.h @@ -10,12 +10,11 @@ #ifndef XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_ #define XENIA_GPU_DXBC_SHADER_TRANSLATOR_H_ -#include - #include #include #include +#include "xenia/base/cvar.h" #include "xenia/base/math.h" #include "xenia/base/string_buffer.h" #include "xenia/gpu/shader_translator.h" diff --git a/src/xenia/gpu/dxbc_shader_translator_alu.cc b/src/xenia/gpu/dxbc_shader_translator_alu.cc index ba49b51f2..bd3a35d96 100644 --- a/src/xenia/gpu/dxbc_shader_translator_alu.cc +++ b/src/xenia/gpu/dxbc_shader_translator_alu.cc @@ -2425,7 +2425,7 @@ void DxbcShaderTranslator::ProcessAluInstruction( return; } - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); // Will be emitted by UpdateInstructionPredication. diff --git a/src/xenia/gpu/dxbc_shader_translator_fetch.cc b/src/xenia/gpu/dxbc_shader_translator_fetch.cc index 703c9277e..f56b6e587 100644 --- a/src/xenia/gpu/dxbc_shader_translator_fetch.cc +++ b/src/xenia/gpu/dxbc_shader_translator_fetch.cc @@ -322,7 +322,7 @@ void DxbcShaderTranslator::ProcessVertexFetchInstruction( } uint32_t result_write_mask = (1 << result_component_count) - 1; - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); // Will be emitted by UpdateInstructionPredication. @@ -1162,7 +1162,7 @@ void DxbcShaderTranslator::ArrayCoordToCubeDirection(uint32_t reg) { void DxbcShaderTranslator::ProcessTextureFetchInstruction( const ParsedTextureFetchInstruction& instr) { - if (FLAGS_dxbc_source_map) { + if (cvars::dxbc_source_map) { instruction_disassembly_buffer_.Reset(); instr.Disassemble(&instruction_disassembly_buffer_); // Will be emitted later explicitly or by UpdateInstructionPredication. diff --git a/src/xenia/gpu/gpu_flags.cc b/src/xenia/gpu/gpu_flags.cc index 2731730be..68f784f19 100644 --- a/src/xenia/gpu/gpu_flags.cc +++ b/src/xenia/gpu/gpu_flags.cc @@ -10,10 +10,10 @@ #include "xenia/gpu/gpu_flags.h" DEFINE_string(trace_gpu_prefix, "scratch/gpu/", - "Prefix path for GPU trace files."); -DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets."); + "Prefix path for GPU trace files.", "GPU"); +DEFINE_bool(trace_gpu_stream, false, "Trace all GPU packets.", "GPU"); DEFINE_string(dump_shaders, "", - "Path to write GPU shaders to as they are compiled."); + "Path to write GPU shaders to as they are compiled.", "GPU"); -DEFINE_bool(vsync, true, "Enable VSYNC."); +DEFINE_bool(vsync, true, "Enable VSYNC.", "GPU"); diff --git a/src/xenia/gpu/gpu_flags.h b/src/xenia/gpu/gpu_flags.h index 98c7e8f0c..17a95807a 100644 --- a/src/xenia/gpu/gpu_flags.h +++ b/src/xenia/gpu/gpu_flags.h @@ -9,8 +9,7 @@ #ifndef XENIA_GPU_GPU_FLAGS_H_ #define XENIA_GPU_GPU_FLAGS_H_ - -#include +#include "xenia/base/cvar.h" DECLARE_string(trace_gpu_prefix); DECLARE_bool(trace_gpu_stream); diff --git a/src/xenia/gpu/graphics_system.cc b/src/xenia/gpu/graphics_system.cc index 6431edfab..0e1c008d8 100644 --- a/src/xenia/gpu/graphics_system.cc +++ b/src/xenia/gpu/graphics_system.cc @@ -113,7 +113,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor, vsync_worker_running_ = true; vsync_worker_thread_ = kernel::object_ref( new kernel::XHostThread(kernel_state_, 128 * 1024, 0, [this]() { - uint64_t vsync_duration = FLAGS_vsync ? 16 : 1; + uint64_t vsync_duration = cvars::vsync ? 16 : 1; uint64_t last_frame_time = Clock::QueryGuestTickCount(); while (vsync_worker_running_) { uint64_t current_time = Clock::QueryGuestTickCount(); @@ -132,7 +132,7 @@ X_STATUS GraphicsSystem::Setup(cpu::Processor* processor, vsync_worker_thread_->set_name("GraphicsSystem Vsync"); vsync_worker_thread_->Create(); - if (FLAGS_trace_gpu_stream) { + if (cvars::trace_gpu_stream) { BeginTracing(); } @@ -270,11 +270,12 @@ void GraphicsSystem::ClearCaches() { } void GraphicsSystem::RequestFrameTrace() { - command_processor_->RequestFrameTrace(xe::to_wstring(FLAGS_trace_gpu_prefix)); + command_processor_->RequestFrameTrace( + xe::to_wstring(cvars::trace_gpu_prefix)); } void GraphicsSystem::BeginTracing() { - command_processor_->BeginTracing(xe::to_wstring(FLAGS_trace_gpu_prefix)); + command_processor_->BeginTracing(xe::to_wstring(cvars::trace_gpu_prefix)); } void GraphicsSystem::EndTracing() { command_processor_->EndTracing(); } diff --git a/src/xenia/gpu/null/premake5.lua b/src/xenia/gpu/null/premake5.lua index 4d902b992..0b4ed0e66 100644 --- a/src/xenia/gpu/null/premake5.lua +++ b/src/xenia/gpu/null/premake5.lua @@ -15,7 +15,4 @@ project("xenia-gpu-null") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/gpu/premake5.lua b/src/xenia/gpu/premake5.lua index 36968d0f1..3dff786a0 100644 --- a/src/xenia/gpu/premake5.lua +++ b/src/xenia/gpu/premake5.lua @@ -20,7 +20,6 @@ project("xenia-gpu") }) includedirs({ project_root.."/third_party/spirv-tools/external/include", - project_root.."/third_party/gflags/src", }) local_platform_files() -- local_platform_files("spirv") @@ -33,7 +32,6 @@ project("xenia-gpu-shader-compiler") language("C++") links({ "dxbc", - "gflags", "glslang-spirv", "spirv-tools", "xenia-base", @@ -42,9 +40,6 @@ project("xenia-gpu-shader-compiler") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({ "shader_compiler_main.cc", "../base/main_"..platform_suffix..".cc", @@ -56,7 +51,6 @@ project("xenia-gpu-shader-compiler") if not os.isfile(user_file) then debugdir(project_root) debugargs({ - "--flagfile=scratch/flags.txt", "2>&1", "1>scratch/stdout-shader-compiler.txt", }) diff --git a/src/xenia/gpu/shader_compiler_main.cc b/src/xenia/gpu/shader_compiler_main.cc index 1acee9b8e..130d2c96d 100644 --- a/src/xenia/gpu/shader_compiler_main.cc +++ b/src/xenia/gpu/shader_compiler_main.cc @@ -7,13 +7,12 @@ ****************************************************************************** */ -#include - #include #include #include #include +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" #include "xenia/base/platform.h" @@ -24,46 +23,51 @@ #include "xenia/gpu/spirv_shader_translator.h" #include "xenia/ui/spirv/spirv_disassembler.h" +<<<<<<< HEAD // For D3DDisassemble: #if XE_PLATFORM_WIN32 #include "xenia/ui/d3d12/d3d12_api.h" #endif // XE_PLATFORM_WIN32 -DEFINE_string(shader_input, "", "Input shader binary file path."); +DEFINE_string(shader_input, "", "Input shader binary file path.", "GPU"); DEFINE_string(shader_input_type, "", - "'vs', 'ps', or unspecified to infer from the given filename."); -DEFINE_string(shader_output, "", "Output shader file path."); + "'vs', 'ps', or unspecified to infer from the given filename.", + "GPU"); +DEFINE_string(shader_output, "", "Output shader file path.", "GPU"); DEFINE_string(shader_output_type, "ucode", - "Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc]."); + "Translator to use: [ucode, glsl45, spirv, spirvtext, dxbc].", + "GPU"); DEFINE_string(shader_output_patch, "", "Tessellation patch type in the generated tessellation " "evaluation (domain) shader, or unspecified to produce a vertex " - "shader: [line, triangle, quad]."); + "shader: [line, triangle, quad].", + "GPU"); DEFINE_bool(shader_output_dxbc_rov, false, - "Output ROV-based output-merger code in DXBC pixel shaders."); + "Output ROV-based output-merger code in DXBC pixel shaders.", + "GPU"); namespace xe { namespace gpu { int shader_compiler_main(const std::vector& args) { ShaderType shader_type; - if (!FLAGS_shader_input_type.empty()) { - if (FLAGS_shader_input_type == "vs") { + if (!cvars::shader_input_type.empty()) { + if (cvars::shader_input_type == "vs") { shader_type = ShaderType::kVertex; - } else if (FLAGS_shader_input_type == "ps") { + } else if (cvars::shader_input_type == "ps") { shader_type = ShaderType::kPixel; } else { XELOGE("Invalid --shader_input_type; must be 'vs' or 'ps'."); return 1; } } else { - auto last_dot = FLAGS_shader_input.find_last_of('.'); + auto last_dot = cvars::shader_input.find_last_of('.'); bool valid_type = false; if (last_dot != std::string::npos) { - if (FLAGS_shader_input.substr(last_dot) == ".vs") { + if (cvars::shader_input.substr(last_dot) == ".vs") { shader_type = ShaderType::kVertex; valid_type = true; - } else if (FLAGS_shader_input.substr(last_dot) == ".ps") { + } else if (cvars::shader_input.substr(last_dot) == ".ps") { shader_type = ShaderType::kPixel; valid_type = true; } @@ -76,9 +80,9 @@ int shader_compiler_main(const std::vector& args) { } } - auto input_file = fopen(FLAGS_shader_input.c_str(), "rb"); + auto input_file = fopen(cvars::shader_input.c_str(), "rb"); if (!input_file) { - XELOGE("Unable to open input file: %s", FLAGS_shader_input.c_str()); + XELOGE("Unable to open input file: %s", cvars::shader_input.c_str()); return 1; } fseek(input_file, 0, SEEK_END); @@ -89,7 +93,7 @@ int shader_compiler_main(const std::vector& args) { fclose(input_file); XELOGI("Opened %s as a %s shader, %" PRId64 " words (%" PRId64 " bytes).", - FLAGS_shader_input.c_str(), + cvars::shader_input.c_str(), shader_type == ShaderType::kVertex ? "vertex" : "pixel", ucode_dwords.size(), ucode_dwords.size() * 4); @@ -99,26 +103,26 @@ int shader_compiler_main(const std::vector& args) { shader_type, ucode_data_hash, ucode_dwords.data(), ucode_dwords.size()); std::unique_ptr translator; - if (FLAGS_shader_output_type == "spirv" || - FLAGS_shader_output_type == "spirvtext") { + if (cvars::shader_output_type == "spirv" || + cvars::shader_output_type == "spirvtext") { translator = std::make_unique(); - } else if (FLAGS_shader_output_type == "glsl45") { + } else if (cvars::shader_output_type == "glsl45") { translator = std::make_unique( GlslShaderTranslator::Dialect::kGL45); - } else if (FLAGS_shader_output_type == "dxbc") { - translator = - std::make_unique(0, FLAGS_shader_output_dxbc_rov); + } else if (cvars::shader_output_type == "dxbc") { + translator = std::make_unique( + 0, cvars::shader_output_dxbc_rov); } else { translator = std::make_unique(); } PrimitiveType patch_primitive_type = PrimitiveType::kNone; if (shader_type == ShaderType::kVertex) { - if (FLAGS_shader_output_patch == "line") { + if (cvars::shader_output_patch == "line") { patch_primitive_type = PrimitiveType::kLinePatch; - } else if (FLAGS_shader_output_patch == "triangle") { + } else if (cvars::shader_output_patch == "triangle") { patch_primitive_type = PrimitiveType::kTrianglePatch; - } else if (FLAGS_shader_output_patch == "quad") { + } else if (cvars::shader_output_patch == "quad") { patch_primitive_type = PrimitiveType::kQuadPatch; } } @@ -129,7 +133,7 @@ int shader_compiler_main(const std::vector& args) { size_t source_data_size = shader->translated_binary().size(); std::unique_ptr spirv_disasm_result; - if (FLAGS_shader_output_type == "spirvtext") { + if (cvars::shader_output_type == "spirvtext") { // Disassemble SPIRV. spirv_disasm_result = xe::ui::spirv::SpirvDisassembler().Disassemble( reinterpret_cast(source_data), source_data_size / 4); @@ -138,7 +142,7 @@ int shader_compiler_main(const std::vector& args) { } #if XE_PLATFORM_WIN32 ID3DBlob* dxbc_disasm_blob = nullptr; - if (FLAGS_shader_output_type == "dxbc") { + if (cvars::shader_output_type == "dxbc") { HMODULE d3d_compiler = LoadLibrary(L"D3DCompiler_47.dll"); if (d3d_compiler != nullptr) { pD3DDisassemble d3d_disassemble = @@ -158,8 +162,8 @@ int shader_compiler_main(const std::vector& args) { } #endif // XE_PLATFORM_WIN32 - if (!FLAGS_shader_output.empty()) { - auto output_file = fopen(FLAGS_shader_output.c_str(), "wb"); + if (!cvars::shader_output.empty()) { + auto output_file = fopen(cvars::shader_output.c_str(), "wb"); fwrite(source_data, 1, source_data_size, output_file); fclose(output_file); } diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index 2ed777ee5..9f9f6da5c 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -9,19 +9,20 @@ #include "xenia/gpu/spirv_shader_translator.h" -#include - #include #include #include #include #include +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation"); -DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation"); +DEFINE_bool(spv_validate, false, "Validate SPIR-V shaders after generation", + "GPU"); +DEFINE_bool(spv_disasm, false, "Disassemble SPIR-V shaders after generation", + "GPU"); namespace xe { namespace gpu { @@ -666,7 +667,7 @@ std::vector SpirvShaderTranslator::CompleteTranslation() { void SpirvShaderTranslator::PostTranslation(Shader* shader) { // Validation. - if (FLAGS_spv_validate) { + if (cvars::spv_validate) { auto validation = validator_.Validate( reinterpret_cast(shader->translated_binary().data()), shader->translated_binary().size() / sizeof(uint32_t)); @@ -676,7 +677,7 @@ void SpirvShaderTranslator::PostTranslation(Shader* shader) { } } - if (FLAGS_spv_disasm) { + if (cvars::spv_disasm) { // TODO(benvanik): only if needed? could be slowish. auto disasm = disassembler_.Disassemble( reinterpret_cast(shader->translated_binary().data()), diff --git a/src/xenia/gpu/texture_dump.cc b/src/xenia/gpu/texture_dump.cc index e21ad34d2..9340a7e33 100644 --- a/src/xenia/gpu/texture_dump.cc +++ b/src/xenia/gpu/texture_dump.cc @@ -7,13 +7,12 @@ ****************************************************************************** */ -#include - +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/gpu/texture_info.h" -DEFINE_bool(texture_dump, false, "Dump textures to DDS"); +DEFINE_bool(texture_dump, false, "Dump textures to DDS", "GPU"); namespace xe { namespace gpu { diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc index 66df289b7..971d8fc16 100644 --- a/src/xenia/gpu/trace_dump.cc +++ b/src/xenia/gpu/trace_dump.cc @@ -9,8 +9,6 @@ #include "xenia/gpu/trace_dump.h" -#include - #include "third_party/stb/stb_image_write.h" #include "xenia/base/logging.h" #include "xenia/base/profiling.h" @@ -28,8 +26,9 @@ #undef _CRT_NONSTDC_NO_DEPRECATE #include "third_party/stb/stb_image_write.h" -DEFINE_string(target_trace_file, "", "Specifies the trace file to load."); -DEFINE_string(trace_dump_path, "", "Output path for dumped files."); +DEFINE_string(target_trace_file, "", "Specifies the trace file to load.", + "GPU"); +DEFINE_string(trace_dump_path, "", "Output path for dumped files.", "GPU"); namespace xe { namespace gpu { @@ -44,11 +43,11 @@ int TraceDump::Main(const std::vector& args) { // Grab path from the flag or unnamed argument. std::wstring path; std::wstring output_path; - if (!FLAGS_target_trace_file.empty()) { + if (!cvars::target_trace_file.empty()) { // Passed as a named argument. // TODO(benvanik): find something better than gflags that supports // unicode. - path = xe::to_wstring(FLAGS_target_trace_file); + path = xe::to_wstring(cvars::target_trace_file); } else if (args.size() >= 2) { // Passed as an unnamed argument. path = args[1]; @@ -79,7 +78,7 @@ int TraceDump::Main(const std::vector& args) { // Root file name for outputs. if (output_path.empty()) { base_output_path_ = - xe::fix_path_separators(xe::to_wstring(FLAGS_trace_dump_path)); + xe::fix_path_separators(xe::to_wstring(cvars::trace_dump_path)); std::wstring output_name = xe::find_name_from_path(xe::fix_path_separators(path)); diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc index 1a3ccb951..4a634be52 100644 --- a/src/xenia/gpu/trace_viewer.cc +++ b/src/xenia/gpu/trace_viewer.cc @@ -9,8 +9,6 @@ #include "xenia/gpu/trace_viewer.h" -#include - #include #include "third_party/half/include/half.hpp" @@ -32,7 +30,8 @@ #include "xenia/ui/window.h" #include "xenia/xbox.h" -DEFINE_string(target_trace_file, "", "Specifies the trace file to load."); +DEFINE_string(target_trace_file, "", "Specifies the trace file to load.", + "GPU"); namespace xe { namespace gpu { @@ -53,11 +52,11 @@ TraceViewer::~TraceViewer() = default; int TraceViewer::Main(const std::vector& args) { // Grab path from the flag or unnamed argument. std::wstring path; - if (!FLAGS_target_trace_file.empty()) { + if (!cvars::target_trace_file.empty()) { // Passed as a named argument. // TODO(benvanik): find something better than gflags that supports // unicode. - path = xe::to_wstring(FLAGS_target_trace_file); + path = xe::to_wstring(cvars::target_trace_file); } else if (args.size() >= 2) { // Passed as an unnamed argument. path = args[1]; diff --git a/src/xenia/gpu/vulkan/pipeline_cache.cc b/src/xenia/gpu/vulkan/pipeline_cache.cc index e9b6a40bd..25d822daf 100644 --- a/src/xenia/gpu/vulkan/pipeline_cache.cc +++ b/src/xenia/gpu/vulkan/pipeline_cache.cc @@ -347,7 +347,7 @@ VkPipeline PipelineCache::GetPipeline(const RenderState* render_state, } // Dump shader disassembly. - if (FLAGS_vulkan_dump_disasm) { + if (cvars::vulkan_dump_disasm) { if (device_->HasEnabledExtension(VK_AMD_SHADER_INFO_EXTENSION_NAME)) { DumpShaderDisasmAMD(pipeline); } else if (device_->device_info().properties.vendorID == 0x10DE) { @@ -387,8 +387,8 @@ bool PipelineCache::TranslateShader(VulkanShader* shader, } // Dump shader files if desired. - if (!FLAGS_dump_shaders.empty()) { - shader->Dump(FLAGS_dump_shaders, "vk"); + if (!cvars::dump_shaders.empty()) { + shader->Dump(cvars::dump_shaders, "vk"); } return shader->is_valid(); @@ -1396,7 +1396,7 @@ PipelineCache::UpdateStatus PipelineCache::UpdateMultisampleState() { // PA_SU_SC_MODE_CNTL MSAA_ENABLE (0x10000) // If set, all samples will be sampled at set locations. Otherwise, they're // all sampled from the pixel center. - if (FLAGS_vulkan_native_msaa) { + if (cvars::vulkan_native_msaa) { auto msaa_num_samples = static_cast((regs.rb_surface_info >> 16) & 0x3); switch (msaa_num_samples) { diff --git a/src/xenia/gpu/vulkan/premake5.lua b/src/xenia/gpu/vulkan/premake5.lua index 82b843b59..2be22502e 100644 --- a/src/xenia/gpu/vulkan/premake5.lua +++ b/src/xenia/gpu/vulkan/premake5.lua @@ -17,9 +17,6 @@ project("xenia-gpu-vulkan") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() files({ "shaders/bin/*.h", @@ -34,7 +31,6 @@ project("xenia-gpu-vulkan-trace-viewer") links({ "aes_128", "capstone", - "gflags", "glslang-spirv", "imgui", "libavcodec", @@ -62,9 +58,6 @@ project("xenia-gpu-vulkan-trace-viewer") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({ "vulkan_trace_viewer_main.cc", "../../base/main_"..platform_suffix..".cc", @@ -91,7 +84,6 @@ project("xenia-gpu-vulkan-trace-viewer") if not os.isfile(user_file) then debugdir(project_root) debugargs({ - "--flagfile=scratch/flags.txt", "2>&1", "1>scratch/stdout-trace-viewer.txt", }) @@ -105,7 +97,6 @@ project("xenia-gpu-vulkan-trace-dump") links({ "aes_128", "capstone", - "gflags", "glslang-spirv", "imgui", "libavcodec", @@ -133,9 +124,6 @@ project("xenia-gpu-vulkan-trace-dump") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({ "vulkan_trace_dump_main.cc", "../../base/main_"..platform_suffix..".cc", @@ -156,7 +144,6 @@ project("xenia-gpu-vulkan-trace-dump") if not os.isfile(user_file) then debugdir(project_root) debugargs({ - "--flagfile=scratch/flags.txt", "2>&1", "1>scratch/stdout-trace-dump.txt", }) diff --git a/src/xenia/gpu/vulkan/render_cache.cc b/src/xenia/gpu/vulkan/render_cache.cc index 075fd54ab..58106cc31 100644 --- a/src/xenia/gpu/vulkan/render_cache.cc +++ b/src/xenia/gpu/vulkan/render_cache.cc @@ -194,7 +194,7 @@ VkResult CachedTileView::Initialize(VkCommandBuffer command_buffer) { image_info.extent.depth = 1; image_info.mipLevels = 1; image_info.arrayLayers = 1; - if (FLAGS_vulkan_native_msaa) { + if (cvars::vulkan_native_msaa) { auto msaa_samples = static_cast(key.msaa_samples); switch (msaa_samples) { case MsaaSamples::k1X: @@ -422,7 +422,7 @@ CachedRenderPass::~CachedRenderPass() { VkResult CachedRenderPass::Initialize() { VkSampleCountFlagBits sample_count; - if (FLAGS_vulkan_native_msaa) { + if (cvars::vulkan_native_msaa) { switch (config.surface_msaa) { case MsaaSamples::k1X: sample_count = VK_SAMPLE_COUNT_1_BIT; @@ -534,7 +534,7 @@ VkResult CachedRenderPass::Initialize() { bool CachedRenderPass::IsCompatible( const RenderConfiguration& desired_config) const { if (config.surface_msaa != desired_config.surface_msaa && - FLAGS_vulkan_native_msaa) { + cvars::vulkan_native_msaa) { return false; } diff --git a/src/xenia/gpu/vulkan/texture_cache.cc b/src/xenia/gpu/vulkan/texture_cache.cc index 029a60b9f..d148c26fb 100644 --- a/src/xenia/gpu/vulkan/texture_cache.cc +++ b/src/xenia/gpu/vulkan/texture_cache.cc @@ -1040,7 +1040,7 @@ bool TextureCache::UploadTexture(VkCommandBuffer command_buffer, unpack_offset += ComputeMipStorage(src, mip); } - if (FLAGS_texture_dump) { + if (cvars::texture_dump) { TextureDump(src, unpack_buffer, unpack_length); } diff --git a/src/xenia/gpu/vulkan/vulkan_command_processor.cc b/src/xenia/gpu/vulkan/vulkan_command_processor.cc index d5c786b37..9b54dfe3e 100644 --- a/src/xenia/gpu/vulkan/vulkan_command_processor.cc +++ b/src/xenia/gpu/vulkan/vulkan_command_processor.cc @@ -356,7 +356,7 @@ void VulkanCommandProcessor::BeginFrame() { // The capture will end when these commands are submitted to the queue. static uint32_t frame = 0; if (device_->is_renderdoc_attached() && !capturing_ && - (FLAGS_vulkan_renderdoc_capture_all || trace_requested_)) { + (cvars::vulkan_renderdoc_capture_all || trace_requested_)) { if (queue_mutex_) { queue_mutex_->lock(); } diff --git a/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc b/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc index fd2fe7789..1e27a4e9a 100644 --- a/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc +++ b/src/xenia/gpu/vulkan/vulkan_gpu_flags.cc @@ -10,7 +10,7 @@ #include "xenia/gpu/vulkan/vulkan_gpu_flags.h" DEFINE_bool(vulkan_renderdoc_capture_all, false, - "Capture everything with RenderDoc."); -DEFINE_bool(vulkan_native_msaa, false, "Use native MSAA"); + "Capture everything with RenderDoc.", "Vulkan"); +DEFINE_bool(vulkan_native_msaa, false, "Use native MSAA", "Vulkan"); DEFINE_bool(vulkan_dump_disasm, false, - "Dump shader disassembly. NVIDIA only supported."); + "Dump shader disassembly. NVIDIA only supported.", "Vulkan"); diff --git a/src/xenia/gpu/vulkan/vulkan_gpu_flags.h b/src/xenia/gpu/vulkan/vulkan_gpu_flags.h index 169e797c8..153bc9bc5 100644 --- a/src/xenia/gpu/vulkan/vulkan_gpu_flags.h +++ b/src/xenia/gpu/vulkan/vulkan_gpu_flags.h @@ -10,9 +10,8 @@ #ifndef XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ #define XENIA_GPU_VULKAN_VULKAN_GPU_FLAGS_H_ -#include - #define FINE_GRAINED_DRAW_SCOPES 1 +#include "xenia/base/cvar.h" DECLARE_bool(vulkan_renderdoc_capture_all); DECLARE_bool(vulkan_native_msaa); diff --git a/src/xenia/hid/hid_demo.cc b/src/xenia/hid/hid_demo.cc index 5afe6eef4..693a5d5c2 100644 --- a/src/xenia/hid/hid_demo.cc +++ b/src/xenia/hid/hid_demo.cc @@ -7,12 +7,11 @@ ****************************************************************************** */ -#include - #include #include "third_party/imgui/imgui.h" #include "xenia/base/clock.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/main.h" #include "xenia/base/threading.h" @@ -28,7 +27,8 @@ #include "xenia/hid/xinput/xinput_hid.h" #endif // XE_PLATFORM_WIN32 -DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]"); +DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]", + "General"); namespace xe { namespace hid { @@ -38,12 +38,12 @@ std::unique_ptr input_system_; std::vector> CreateInputDrivers( ui::Window* window) { std::vector> drivers; - if (FLAGS_hid.compare("nop") == 0) { + if (cvars::hid.compare("nop") == 0) { drivers.emplace_back(xe::hid::nop::Create(window)); #if XE_PLATFORM_WIN32 - } else if (FLAGS_hid.compare("winkey") == 0) { + } else if (cvars::hid.compare("winkey") == 0) { drivers.emplace_back(xe::hid::winkey::Create(window)); - } else if (FLAGS_hid.compare("xinput") == 0) { + } else if (cvars::hid.compare("xinput") == 0) { drivers.emplace_back(xe::hid::xinput::Create(window)); #endif // XE_PLATFORM_WIN32 } else { diff --git a/src/xenia/hid/hid_flags.h b/src/xenia/hid/hid_flags.h index ec43d1d7d..f7321aec3 100644 --- a/src/xenia/hid/hid_flags.h +++ b/src/xenia/hid/hid_flags.h @@ -10,6 +10,4 @@ #ifndef XENIA_HID_HID_FLAGS_H_ #define XENIA_HID_HID_FLAGS_H_ -#include - #endif // XENIA_HID_HID_FLAGS_H_ diff --git a/src/xenia/hid/nop/premake5.lua b/src/xenia/hid/nop/premake5.lua index b953b1773..53fefaee5 100644 --- a/src/xenia/hid/nop/premake5.lua +++ b/src/xenia/hid/nop/premake5.lua @@ -12,7 +12,4 @@ project("xenia-hid-nop") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/hid/premake5.lua b/src/xenia/hid/premake5.lua index ea7b6afbf..37f96f414 100644 --- a/src/xenia/hid/premake5.lua +++ b/src/xenia/hid/premake5.lua @@ -11,9 +11,6 @@ project("xenia-hid") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() removefiles({"*_demo.cc"}) @@ -23,7 +20,6 @@ project("xenia-hid-demo") kind("WindowedApp") language("C++") links({ - "gflags", "glew", "imgui", "volk", @@ -37,9 +33,6 @@ project("xenia-hid-demo") "GLEW_STATIC=1", "GLEW_MX=1", }) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({ "hid_demo.cc", "../base/main_"..platform_suffix..".cc", diff --git a/src/xenia/hid/winkey/premake5.lua b/src/xenia/hid/winkey/premake5.lua index d0edd8fb6..0e3b86580 100644 --- a/src/xenia/hid/winkey/premake5.lua +++ b/src/xenia/hid/winkey/premake5.lua @@ -13,7 +13,4 @@ project("xenia-hid-winkey") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/hid/xinput/premake5.lua b/src/xenia/hid/xinput/premake5.lua index 506ea5e25..6247cf98c 100644 --- a/src/xenia/hid/xinput/premake5.lua +++ b/src/xenia/hid/xinput/premake5.lua @@ -12,7 +12,4 @@ project("xenia-hid-xinput") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() diff --git a/src/xenia/kernel/kernel_flags.cc b/src/xenia/kernel/kernel_flags.cc new file mode 100644 index 000000000..331552950 --- /dev/null +++ b/src/xenia/kernel/kernel_flags.cc @@ -0,0 +1,16 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/kernel/kernel_flags.h" + +DEFINE_bool(headless, false, + "Don't display any UI, using defaults for prompts as needed.", + "Other"); +DEFINE_bool(log_high_frequency_kernel_calls, false, + "Log kernel calls with the kHighFrequency tag.", "Kernel"); diff --git a/src/xenia/kernel/kernel_flags.h b/src/xenia/kernel/kernel_flags.h new file mode 100644 index 000000000..04a6d6ebf --- /dev/null +++ b/src/xenia/kernel/kernel_flags.h @@ -0,0 +1,17 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2013 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_KERNEL_KERNEL_FLAGS_H_ +#define XENIA_KERNEL_KERNEL_FLAGS_H_ +#include "xenia/base/cvar.h" + +DECLARE_bool(headless); +DECLARE_bool(log_high_frequency_kernel_calls); + +#endif // XENIA_KERNEL_KERNEL_FLAGS_H_ diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 3d28b374a..57097148e 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/kernel_state.h" -#include - #include #include "xenia/base/assert.h" @@ -29,9 +27,6 @@ #include "xenia/kernel/xobject.h" #include "xenia/kernel/xthread.h" -DEFINE_bool(headless, false, - "Don't display any UI, using defaults for prompts as needed."); - namespace xe { namespace kernel { diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index cc92a9813..19fbc5825 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -10,8 +10,6 @@ #ifndef XENIA_KERNEL_KERNEL_STATE_H_ #define XENIA_KERNEL_KERNEL_STATE_H_ -#include - #include #include #include @@ -20,6 +18,7 @@ #include #include "xenia/base/bit_map.h" +#include "xenia/base/cvar.h" #include "xenia/base/mutex.h" #include "xenia/cpu/export_resolver.h" #include "xenia/kernel/util/native_list.h" @@ -39,8 +38,6 @@ class Processor; } // namespace cpu } // namespace xe -DECLARE_bool(headless); - namespace xe { namespace kernel { diff --git a/src/xenia/kernel/premake5.lua b/src/xenia/kernel/premake5.lua index 0aba1a30e..808dc8899 100644 --- a/src/xenia/kernel/premake5.lua +++ b/src/xenia/kernel/premake5.lua @@ -16,9 +16,6 @@ project("xenia-kernel") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) recursive_platform_files() files({ "debug_visualizers.natvis", diff --git a/src/xenia/kernel/user_module.cc b/src/xenia/kernel/user_module.cc index 6a4bb846d..f5a35c8eb 100644 --- a/src/xenia/kernel/user_module.cc +++ b/src/xenia/kernel/user_module.cc @@ -20,7 +20,7 @@ #include "xenia/kernel/xfile.h" #include "xenia/kernel/xthread.h" -DEFINE_bool(xex_apply_patches, true, "Apply XEX patches."); +DEFINE_bool(xex_apply_patches, true, "Apply XEX patches.", "Kernel"); namespace xe { namespace kernel { @@ -102,7 +102,7 @@ X_STATUS UserModule::LoadFromFile(std::string path) { return result; } - if (FLAGS_xex_apply_patches) { + if (cvars::xex_apply_patches) { // Search for xexp patch file auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p"); diff --git a/src/xenia/kernel/util/shim_utils.cc b/src/xenia/kernel/util/shim_utils.cc index 5c8dc2850..4da37acc0 100644 --- a/src/xenia/kernel/util/shim_utils.cc +++ b/src/xenia/kernel/util/shim_utils.cc @@ -9,9 +9,6 @@ #include "xenia/kernel/util/shim_utils.h" -DEFINE_bool(log_high_frequency_kernel_calls, false, - "Log kernel calls with the kHighFrequency tag."); - namespace xe { namespace kernel { namespace shim { diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 73c4ca62f..57d5d1e98 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -10,8 +10,6 @@ #ifndef XENIA_KERNEL_UTIL_SHIM_UTILS_H_ #define XENIA_KERNEL_UTIL_SHIM_UTILS_H_ -#include - #include #include @@ -21,10 +19,9 @@ #include "xenia/base/string_buffer.h" #include "xenia/cpu/export_resolver.h" #include "xenia/cpu/ppc/ppc_context.h" +#include "xenia/kernel/kernel_flags.h" #include "xenia/kernel/kernel_state.h" -DECLARE_bool(log_high_frequency_kernel_calls); - namespace xe { namespace kernel { @@ -482,7 +479,7 @@ xe::cpu::Export* RegisterExport(R (*fn)(Ps&...), const char* name, auto params = std::make_tuple(Ps(init)...); if (export_entry->tags & xe::cpu::ExportTag::kLog && (!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) || - FLAGS_log_high_frequency_kernel_calls)) { + cvars::log_high_frequency_kernel_calls)) { PrintKernelCall(export_entry, params); } auto result = @@ -516,7 +513,7 @@ xe::cpu::Export* RegisterExport(void (*fn)(Ps&...), const char* name, auto params = std::make_tuple(Ps(init)...); if (export_entry->tags & xe::cpu::ExportTag::kLog && (!(export_entry->tags & xe::cpu::ExportTag::kHighFrequency) || - FLAGS_log_high_frequency_kernel_calls)) { + cvars::log_high_frequency_kernel_calls)) { PrintKernelCall(export_entry, params); } KernelTrampoline(FN, std::forward>(params), diff --git a/src/xenia/kernel/xam/xam_nui.cc b/src/xenia/kernel/xam/xam_nui.cc index 1327bef3d..3fbeb7663 100644 --- a/src/xenia/kernel/xam/xam_nui.cc +++ b/src/xenia/kernel/xam/xam_nui.cc @@ -9,6 +9,7 @@ #include "xenia/base/logging.h" #include "xenia/emulator.h" +#include "xenia/kernel/kernel_flags.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" @@ -43,7 +44,7 @@ dword_result_t XamShowNuiTroubleshooterUI(unknown_t unk1, unknown_t unk2, // unk1 is 0xFF - possibly user index? // unk2, unk3 appear to always be zero. - if (FLAGS_headless) { + if (cvars::headless) { return 0; } diff --git a/src/xenia/kernel/xam/xam_ui.cc b/src/xenia/kernel/xam/xam_ui.cc index 4ada0d77e..a3871577b 100644 --- a/src/xenia/kernel/xam/xam_ui.cc +++ b/src/xenia/kernel/xam/xam_ui.cc @@ -10,6 +10,7 @@ #include "third_party/imgui/imgui.h" #include "xenia/base/logging.h" #include "xenia/emulator.h" +#include "xenia/kernel/kernel_flags.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xam/xam_private.h" @@ -111,7 +112,7 @@ dword_result_t XamShowMessageBoxUI(dword_t user_index, lpwstring_t title_ptr, } uint32_t chosen_button; - if (FLAGS_headless) { + if (cvars::headless) { // Auto-pick the focused button. chosen_button = active_button; } else { @@ -231,7 +232,7 @@ dword_result_t XamShowKeyboardUI(dword_t user_index, dword_t flags, return X_ERROR_INVALID_PARAMETER; } - if (FLAGS_headless) { + if (cvars::headless) { // Redirect default_text back into the buffer. std::memset(buffer, 0, buffer_length * 2); if (default_text) { @@ -309,7 +310,7 @@ dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type, DECLARE_XAM_EXPORT1(XamShowDeviceSelectorUI, kUI, kImplemented); void XamShowDirtyDiscErrorUI(dword_t user_index) { - if (FLAGS_headless) { + if (cvars::headless) { assert_always(); exit(1); return; diff --git a/src/xenia/kernel/xboxkrnl/cert_monitor.cc b/src/xenia/kernel/xboxkrnl/cert_monitor.cc index 9f552b9c3..4ce3aeb08 100644 --- a/src/xenia/kernel/xboxkrnl/cert_monitor.cc +++ b/src/xenia/kernel/xboxkrnl/cert_monitor.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" -#include - #include #include "xenia/base/clock.h" diff --git a/src/xenia/kernel/xboxkrnl/debug_monitor.cc b/src/xenia/kernel/xboxkrnl/debug_monitor.cc index cfd4ef967..95138d08a 100644 --- a/src/xenia/kernel/xboxkrnl/debug_monitor.cc +++ b/src/xenia/kernel/xboxkrnl/debug_monitor.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" -#include - #include #include "xenia/base/clock.h" @@ -47,7 +45,7 @@ void KeDebugMonitorCallback(cpu::ppc::PPCContext* ppc_context, XELOGI("KeDebugMonitorCallback(%u, %08x)", static_cast(id), arg); - if (!FLAGS_kernel_pix) { + if (!cvars::kernel_pix) { SHIM_SET_RETURN_32(-1); return; } diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc index f38d27d35..008bb0fe3 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" -#include - #include #include "xenia/base/clock.h" @@ -27,18 +25,19 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_private.h" #include "xenia/kernel/xthread.h" -DEFINE_string(cl, "", "Specify additional command-line provided to guest."); +DEFINE_string(cl, "", "Specify additional command-line provided to guest.", + "Kernel"); -DEFINE_bool(kernel_debug_monitor, false, "Enable debug monitor."); -DEFINE_bool(kernel_cert_monitor, false, "Enable cert monitor."); -DEFINE_bool(kernel_pix, false, "Enable PIX."); +DEFINE_bool(kernel_debug_monitor, false, "Enable debug monitor.", "Kernel"); +DEFINE_bool(kernel_cert_monitor, false, "Enable cert monitor.", "Kernel"); +DEFINE_bool(kernel_pix, false, "Enable PIX.", "Kernel"); namespace xe { namespace kernel { namespace xboxkrnl { bool XboxkrnlModule::SendPIXCommand(const char* cmd) { - if (!FLAGS_kernel_pix) { + if (!cvars::kernel_pix) { return false; } @@ -103,7 +102,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // Offset 0x18 is a 4b pointer to a handler function that seems to take two // arguments. If we wanted to see what would happen we could fake that. uint32_t pKeDebugMonitorData; - if (!FLAGS_kernel_debug_monitor) { + if (!cvars::kernel_debug_monitor) { pKeDebugMonitorData = memory_->SystemHeapAlloc(4); auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData); xe::store_and_swap(lpKeDebugMonitorData, 0); @@ -125,7 +124,7 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // KeCertMonitorData (?*) // Always set to zero, ignored. uint32_t pKeCertMonitorData; - if (!FLAGS_kernel_cert_monitor) { + if (!cvars::kernel_cert_monitor) { pKeCertMonitorData = memory_->SystemHeapAlloc(4); auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData); xe::store_and_swap(lpKeCertMonitorData, 0); @@ -187,8 +186,8 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // Always set to "default.xex" (with quotes) for now. // TODO(gibbed): set this to the actual module name. std::string command_line("\"default.xex\""); - if (FLAGS_cl.length()) { - command_line += " " + FLAGS_cl; + if (cvars::cl.length()) { + command_line += " " + cvars::cl; } uint32_t command_line_length = xe::align(static_cast(command_line.length()) + 1, 1024u); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc index 4c1085c7c..c2b3b273a 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_video.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/xboxkrnl/xboxkrnl_video.h" -#include - #include "xenia/base/logging.h" #include "xenia/emulator.h" #include "xenia/gpu/graphics_system.h" @@ -24,9 +22,11 @@ DEFINE_int32(kernel_display_gamma_type, 1, "Display gamma type: 0 - linear, 1 - sRGB, 2 - TV (BT.709), " - "3 - power specified via kernel_display_gamma_power."); + "3 - power specified via kernel_display_gamma_power.", + "Kernel"); DEFINE_double(kernel_display_gamma_power, 2.22222233, - "Display gamma to use with kernel_display_gamma_type 3."); + "Display gamma to use with kernel_display_gamma_type 3.", + "Kernel"); namespace xe { namespace kernel { @@ -51,8 +51,8 @@ void VdGetCurrentDisplayGamma(lpdword_t type_ptr, lpfloat_t power_ptr) { // 3 - use the power written to *power_ptr. // Anything else - linear. // Used in D3D SetGammaRamp/SetPWLGamma to adjust the ramp for the display. - *type_ptr = uint32_t(FLAGS_kernel_display_gamma_type); - *power_ptr = float(FLAGS_kernel_display_gamma_power); + *type_ptr = uint32_t(cvars::kernel_display_gamma_type); + *power_ptr = float(cvars::kernel_display_gamma_power); } DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayGamma, kVideo, kStub); diff --git a/src/xenia/kernel/xthread.cc b/src/xenia/kernel/xthread.cc index 97bc8d4ad..7ba7db2eb 100644 --- a/src/xenia/kernel/xthread.cc +++ b/src/xenia/kernel/xthread.cc @@ -9,8 +9,6 @@ #include "xenia/kernel/xthread.h" -#include - #include #ifdef XE_PLATFORM_WIN32 @@ -33,9 +31,9 @@ #include "xenia/kernel/xmutant.h" DEFINE_bool(ignore_thread_priorities, true, - "Ignores game-specified thread priorities."); + "Ignores game-specified thread priorities.", "Kernel"); DEFINE_bool(ignore_thread_affinities, true, - "Ignores game-specified thread affinities."); + "Ignores game-specified thread affinities.", "Kernel"); namespace xe { namespace kernel { @@ -416,7 +414,7 @@ X_STATUS XThread::Create() { return X_STATUS_NO_MEMORY; } - if (!FLAGS_ignore_thread_affinities) { + if (!cvars::ignore_thread_affinities) { thread_->set_affinity_mask(proc_mask); } @@ -698,7 +696,7 @@ void XThread::SetPriority(int32_t increment) { } else { target_priority = xe::threading::ThreadPriority::kNormal; } - if (!FLAGS_ignore_thread_priorities) { + if (!cvars::ignore_thread_priorities) { thread_->set_priority(target_priority); } } @@ -719,7 +717,7 @@ void XThread::SetAffinity(uint32_t affinity) { } SetActiveCpu(GetFakeCpuNumber(affinity)); affinity_ = affinity; - if (!FLAGS_ignore_thread_affinities) { + if (!cvars::ignore_thread_affinities) { thread_->set_affinity_mask(affinity); } } diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index 370c5bad4..6b27db978 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -9,13 +9,12 @@ #include "xenia/memory.h" -#include - #include #include #include "xenia/base/byte_stream.h" #include "xenia/base/clock.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/base/threading.h" @@ -24,15 +23,14 @@ // TODO(benvanik): move xbox.h out #include "xenia/xbox.h" -DEFINE_bool(protect_zero, true, "Protect the zero page from reads and writes."); +DEFINE_bool(protect_zero, true, "Protect the zero page from reads and writes.", + "Memory"); DEFINE_bool(protect_on_release, false, - "Protect released memory to prevent accesses."); - + "Protect released memory to prevent accesses.", "Memory"); DEFINE_bool(scribble_heap, false, - "Scribble 0xCD into all allocated heap memory."); + "Scribble 0xCD into all allocated heap memory.", "Memory"); namespace xe { - uint32_t get_page_count(uint32_t value, uint32_t page_size) { return xe::round_up(value, page_size) / page_size; } @@ -54,10 +52,10 @@ uint32_t get_page_count(uint32_t value, uint32_t page_size) { * * We create our own heap of committed memory that lives at * memory_HEAP_LOW to memory_HEAP_HIGH - all normal user allocations - * come from there. Since the Xbox has no paging, we know that the size of this - * heap will never need to be larger than ~512MB (realistically, smaller than - * that). We place it far away from the XEX data and keep the memory around it - * uncommitted so that we have some warning if things go astray. + * come from there. Since the Xbox has no paging, we know that the size of + * this heap will never need to be larger than ~512MB (realistically, smaller + * than that). We place it far away from the XEX data and keep the memory + * around it uncommitted so that we have some warning if things go astray. * * For XEX/GPU/etc data we allow placement allocations (base_address != 0) and * commit the requested memory as needed. This bypasses the standard heap, but @@ -182,8 +180,8 @@ bool Memory::Initialize() { heaps_.v00000000.AllocFixed( 0x00000000, 0x10000, 0x10000, kMemoryAllocationReserve | kMemoryAllocationCommit, - !FLAGS_protect_zero ? kMemoryProtectRead | kMemoryProtectWrite - : kMemoryProtectNoAccess); + !cvars::protect_zero ? kMemoryProtectRead | kMemoryProtectWrite + : kMemoryProtectNoAccess); heaps_.physical.AllocFixed(0x1FFF0000, 0x10000, 0x10000, kMemoryAllocationReserve, kMemoryProtectNoAccess); @@ -863,7 +861,7 @@ bool BaseHeap::AllocFixed(uint32_t base_address, uint32_t size, return false; } - if (FLAGS_scribble_heap && protect & kMemoryProtectWrite) { + if (cvars::scribble_heap && protect & kMemoryProtectWrite) { std::memset(result, 0xCD, page_count * page_size_); } } @@ -1011,7 +1009,7 @@ bool BaseHeap::AllocRange(uint32_t low_address, uint32_t high_address, return false; } - if (FLAGS_scribble_heap && (protect & kMemoryProtectWrite)) { + if (cvars::scribble_heap && (protect & kMemoryProtectWrite)) { std::memset(result, 0xCD, page_count * page_size_); } } @@ -1096,10 +1094,10 @@ bool BaseHeap::Release(uint32_t base_address, uint32_t* out_region_size) { xe::memory::page_size() == 0 && ((base_page_number * page_size_) % xe::memory::page_size() == 0))) { - // TODO(benvanik): figure out why games are using memory after releasing it. - // It's possible this is some virtual/physical stuff where the GPU still can - // access it. - if (FLAGS_protect_on_release) { + // TODO(benvanik): figure out why games are using memory after releasing + // it. It's possible this is some virtual/physical stuff where the GPU + // still can access it. + if (cvars::protect_on_release) { if (!xe::memory::Protect( membase_ + heap_base_ + base_page_number * page_size_, base_page_entry.region_page_count * page_size_, @@ -1323,7 +1321,8 @@ bool PhysicalHeap::Alloc(uint32_t size, uint32_t alignment, bool top_down, uint32_t* out_address) { *out_address = 0; - // Default top-down. Since parent heap is bottom-up this prevents collisions. + // Default top-down. Since parent heap is bottom-up this prevents + // collisions. top_down = true; // Adjust alignment size our page size differs from the parent. @@ -1462,7 +1461,7 @@ bool PhysicalHeap::Release(uint32_t base_address, uint32_t* out_region_size) { cpu::MMIOHandler::global_handler()->InvalidateRange(base_address, region_size); TriggerWatches(base_address, region_size, true, true, - !FLAGS_protect_on_release); + !cvars::protect_on_release); } if (!parent_heap_->Release(parent_base_address, out_region_size)) { diff --git a/src/xenia/premake5.lua b/src/xenia/premake5.lua index 1d674f198..b403f42f9 100644 --- a/src/xenia/premake5.lua +++ b/src/xenia/premake5.lua @@ -11,7 +11,4 @@ project("xenia-core") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({"*.h", "*.cc"}) diff --git a/src/xenia/tools/api-scanner/api_scanner_main.cc b/src/xenia/tools/api-scanner/api_scanner_main.cc index 46796974d..738e9622d 100644 --- a/src/xenia/tools/api-scanner/api_scanner_main.cc +++ b/src/xenia/tools/api-scanner/api_scanner_main.cc @@ -7,7 +7,6 @@ ****************************************************************************** */ -#include #include "api_scanner_loader.h" namespace xe { @@ -20,8 +19,8 @@ int api_scanner_main(std::vector& args) { if (args.size() == 2 || !FLAGS_target.empty()) { apiscanner_loader loader_; - std::wstring target(FLAGS_target.empty() ? args[1] - : xe::to_wstring(FLAGS_target)); + std::wstring target(cvars::target.empty() ? args[1] + : xe::to_wstring(cvars::target)); std::wstring target_abs = xe::to_absolute_path(target); diff --git a/src/xenia/ui/d3d12/d3d12_context.cc b/src/xenia/ui/d3d12/d3d12_context.cc index 69731f483..fa3664eb8 100644 --- a/src/xenia/ui/d3d12/d3d12_context.cc +++ b/src/xenia/ui/d3d12/d3d12_context.cc @@ -9,19 +9,17 @@ #include "xenia/ui/d3d12/d3d12_context.h" -#include - #include +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" -#include "xenia/gpu/gpu_flags.h" #include "xenia/ui/d3d12/d3d12_immediate_drawer.h" #include "xenia/ui/d3d12/d3d12_provider.h" #include "xenia/ui/window.h" DEFINE_bool(d3d12_random_clear_color, false, - "Randomize presentation back buffer clear color."); + "Randomize presentation back buffer clear color.", "D3D12"); namespace xe { namespace ui { @@ -267,7 +265,7 @@ void D3D12Context::BeginSwap() { graphics_command_list->OMSetRenderTargets(1, &back_buffer_rtv, TRUE, nullptr); float clear_color[4]; - if (FLAGS_d3d12_random_clear_color) { + if (cvars::d3d12_random_clear_color) { clear_color[0] = rand() / float(RAND_MAX); // NOLINT(runtime/threadsafe_fn) clear_color[1] = 1.0f; @@ -303,7 +301,7 @@ void D3D12Context::EndSwap() { graphics_command_list->ResourceBarrier(1, &barrier); command_list->Execute(); // Present and check if the context was lost. - HRESULT result = swap_chain_->Present(FLAGS_vsync ? 1 : 0, 0); + HRESULT result = swap_chain_->Present(0, 0); if (result == DXGI_ERROR_DEVICE_RESET || result == DXGI_ERROR_DEVICE_REMOVED) { context_lost_ = true; diff --git a/src/xenia/ui/d3d12/d3d12_provider.cc b/src/xenia/ui/d3d12/d3d12_provider.cc index c809389f1..7031f4fb1 100644 --- a/src/xenia/ui/d3d12/d3d12_provider.cc +++ b/src/xenia/ui/d3d12/d3d12_provider.cc @@ -9,18 +9,19 @@ #include "xenia/ui/d3d12/d3d12_provider.h" -#include - #include #include +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/ui/d3d12/d3d12_context.h" -DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer."); +DEFINE_bool(d3d12_debug, false, "Enable Direct3D 12 and DXGI debug layer.", + "D3D12"); DEFINE_int32(d3d12_adapter, -1, "Index of the DXGI adapter to use. " - "-1 for any physical adapter, -2 for WARP software rendering."); + "-1 for any physical adapter, -2 for WARP software rendering.", + "D3D12"); namespace xe { namespace ui { @@ -107,7 +108,7 @@ D3D12Provider::InitializationResult D3D12Provider::Initialize() { } // Enable the debug layer. - bool debug = FLAGS_d3d12_debug; + bool debug = cvars::d3d12_debug; if (debug) { ID3D12Debug* debug_interface; if (SUCCEEDED( @@ -136,11 +137,11 @@ D3D12Provider::InitializationResult D3D12Provider::Initialize() { if (SUCCEEDED(adapter->GetDesc1(&adapter_desc))) { if (SUCCEEDED(pfn_d3d12_create_device_(adapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr))) { - if (FLAGS_d3d12_adapter >= 0) { - if (adapter_index == FLAGS_d3d12_adapter) { + if (cvars::d3d12_adapter >= 0) { + if (adapter_index == cvars::d3d12_adapter) { break; } - } else if (FLAGS_d3d12_adapter == -2) { + } else if (cvars::d3d12_adapter == -2) { if (adapter_desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) { break; } diff --git a/src/xenia/ui/premake5.lua b/src/xenia/ui/premake5.lua index 6fe5ebfc8..c5dbd84af 100644 --- a/src/xenia/ui/premake5.lua +++ b/src/xenia/ui/premake5.lua @@ -11,8 +11,5 @@ project("xenia-ui") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) local_platform_files() removefiles({"*_demo.cc"}) diff --git a/src/xenia/ui/spirv/premake5.lua b/src/xenia/ui/spirv/premake5.lua index 423ad7bb6..9988a051a 100644 --- a/src/xenia/ui/spirv/premake5.lua +++ b/src/xenia/ui/spirv/premake5.lua @@ -14,7 +14,6 @@ project("xenia-ui-spirv") defines({ }) includedirs({ - project_root.."/third_party/gflags/src", project_root.."/third_party/spirv-tools/external/include", }) local_platform_files() diff --git a/src/xenia/ui/vulkan/premake5.lua b/src/xenia/ui/vulkan/premake5.lua index 8246ef249..5d04b98d2 100644 --- a/src/xenia/ui/vulkan/premake5.lua +++ b/src/xenia/ui/vulkan/premake5.lua @@ -14,7 +14,6 @@ project("xenia-ui-vulkan") defines({ }) includedirs({ - project_root.."/third_party/gflags/src", project_root.."/third_party/vulkan/", }) local_platform_files() @@ -29,7 +28,6 @@ project("xenia-ui-window-vulkan-demo") kind("WindowedApp") language("C++") links({ - "gflags", "imgui", "volk", "xenia-base", @@ -40,7 +38,6 @@ project("xenia-ui-window-vulkan-demo") defines({ }) includedirs({ - project_root.."/third_party/gflags/src", project_root.."/third_party/vulkan/", }) files({ diff --git a/src/xenia/ui/vulkan/vulkan.cc b/src/xenia/ui/vulkan/vulkan.cc index 77c8fb548..5bc610557 100644 --- a/src/xenia/ui/vulkan/vulkan.cc +++ b/src/xenia/ui/vulkan/vulkan.cc @@ -9,8 +9,10 @@ #include "xenia/ui/vulkan/vulkan.h" -DEFINE_bool(vulkan_validation, false, "Enable Vulkan validation layers."); +DEFINE_bool(vulkan_validation, false, "Enable Vulkan validation layers.", + "Vulkan"); DEFINE_bool(vulkan_primary_queue_only, false, "Force the use of the primary queue, ignoring any additional that " - "may be present."); + "may be present.", + "Vulkan"); diff --git a/src/xenia/ui/vulkan/vulkan.h b/src/xenia/ui/vulkan/vulkan.h index 7d4887418..cebd210ca 100644 --- a/src/xenia/ui/vulkan/vulkan.h +++ b/src/xenia/ui/vulkan/vulkan.h @@ -10,8 +10,6 @@ #ifndef XENIA_UI_VULKAN_VULKAN_H_ #define XENIA_UI_VULKAN_VULKAN_H_ -#include - #include "xenia/base/platform.h" #if XE_PLATFORM_WIN32 @@ -25,6 +23,7 @@ // We use a loader with its own function prototypes. #include "third_party/volk/volk.h" #include "third_party/vulkan/vulkan.h" +#include "xenia/base/cvar.h" #define XELOGVK XELOGI diff --git a/src/xenia/ui/vulkan/vulkan_device.cc b/src/xenia/ui/vulkan/vulkan_device.cc index a6d31c174..275a45070 100644 --- a/src/xenia/ui/vulkan/vulkan_device.cc +++ b/src/xenia/ui/vulkan/vulkan_device.cc @@ -9,8 +9,6 @@ #include "xenia/ui/vulkan/vulkan_device.h" -#include - #include #include #include @@ -33,7 +31,7 @@ namespace ui { namespace vulkan { VulkanDevice::VulkanDevice(VulkanInstance* instance) : instance_(instance) { - if (FLAGS_vulkan_validation) { + if (cvars::vulkan_validation) { DeclareRequiredLayer("VK_LAYER_LUNARG_standard_validation", Version::Make(0, 0, 0), true); // DeclareRequiredLayer("VK_LAYER_GOOGLE_unique_objects", Version::Make(0, @@ -150,7 +148,7 @@ bool VulkanDevice::Initialize(DeviceInfo device_info) { } // Some tools *cough* renderdoc *cough* can't handle multiple queues. - if (FLAGS_vulkan_primary_queue_only) { + if (cvars::vulkan_primary_queue_only) { queue_count = 1; } diff --git a/src/xenia/ui/vulkan/vulkan_instance.cc b/src/xenia/ui/vulkan/vulkan_instance.cc index 893437c2b..fd265a405 100644 --- a/src/xenia/ui/vulkan/vulkan_instance.cc +++ b/src/xenia/ui/vulkan/vulkan_instance.cc @@ -9,8 +9,6 @@ #include "xenia/ui/vulkan/vulkan_instance.h" -#include - #include #include #include @@ -38,7 +36,7 @@ namespace ui { namespace vulkan { VulkanInstance::VulkanInstance() { - if (FLAGS_vulkan_validation) { + if (cvars::vulkan_validation) { DeclareRequiredLayer("VK_LAYER_LUNARG_standard_validation", Version::Make(0, 0, 0), true); // DeclareRequiredLayer("VK_LAYER_GOOGLE_unique_objects", Version::Make(0, diff --git a/src/xenia/ui/vulkan/vulkan_provider.cc b/src/xenia/ui/vulkan/vulkan_provider.cc index 1e1d005c4..119f03992 100644 --- a/src/xenia/ui/vulkan/vulkan_provider.cc +++ b/src/xenia/ui/vulkan/vulkan_provider.cc @@ -9,8 +9,6 @@ #include "xenia/ui/vulkan/vulkan_provider.h" -#include - #include #include "xenia/base/logging.h" @@ -19,7 +17,8 @@ #include "xenia/ui/vulkan/vulkan_instance.h" #include "xenia/ui/vulkan/vulkan_util.h" -DEFINE_uint64(vulkan_device_index, 0, "Index of the physical device to use."); +DEFINE_uint64(vulkan_device_index, 0, "Index of the physical device to use.", + "Vulkan"); namespace xe { namespace ui { @@ -73,7 +72,7 @@ bool VulkanProvider::Initialize() { return false; } size_t device_index = - std::min(available_devices.size(), FLAGS_vulkan_device_index); + std::min(available_devices.size(), cvars::vulkan_device_index); auto& device_info = available_devices[device_index]; // Create the device. diff --git a/src/xenia/ui/vulkan/vulkan_swap_chain.cc b/src/xenia/ui/vulkan/vulkan_swap_chain.cc index 25ef70dbe..fda0c402e 100644 --- a/src/xenia/ui/vulkan/vulkan_swap_chain.cc +++ b/src/xenia/ui/vulkan/vulkan_swap_chain.cc @@ -9,12 +9,11 @@ #include "xenia/ui/vulkan/vulkan_swap_chain.h" -#include - #include #include #include "xenia/base/assert.h" +#include "xenia/base/cvar.h" #include "xenia/base/logging.h" #include "xenia/base/math.h" #include "xenia/ui/vulkan/vulkan.h" @@ -23,7 +22,7 @@ #include "xenia/ui/vulkan/vulkan_util.h" DEFINE_bool(vulkan_random_clear_color, false, - "Randomizes framebuffer clear color."); + "Randomizes framebuffer clear color.", "Vulkan"); namespace xe { namespace ui { @@ -583,7 +582,7 @@ VkResult VulkanSwapChain::Begin() { clear_color.float32[1] = 238 / 255.0f; clear_color.float32[2] = 238 / 255.0f; clear_color.float32[3] = 1.0f; - if (FLAGS_vulkan_random_clear_color) { + if (cvars::vulkan_random_clear_color) { clear_color.float32[0] = rand() / static_cast(RAND_MAX); // NOLINT(runtime/threadsafe_fn) clear_color.float32[1] = 1.0f; diff --git a/src/xenia/ui/vulkan/vulkan_util.h b/src/xenia/ui/vulkan/vulkan_util.h index ba93ff132..ac47e5d4b 100644 --- a/src/xenia/ui/vulkan/vulkan_util.h +++ b/src/xenia/ui/vulkan/vulkan_util.h @@ -12,6 +12,7 @@ #include #include +#include #include "xenia/ui/vulkan/vulkan.h" diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc index 13b3689af..2895c2a6e 100644 --- a/src/xenia/ui/window_demo.cc +++ b/src/xenia/ui/window_demo.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include #include "third_party/imgui/imgui.h" diff --git a/src/xenia/vfs/premake5.lua b/src/xenia/vfs/premake5.lua index ea174e3e0..fc8b4a545 100644 --- a/src/xenia/vfs/premake5.lua +++ b/src/xenia/vfs/premake5.lua @@ -11,9 +11,6 @@ project("xenia-vfs") }) defines({ }) - includedirs({ - project_root.."/third_party/gflags/src", - }) recursive_platform_files() removefiles({"vfs_dump.cc"}) @@ -22,14 +19,10 @@ project("xenia-vfs-dump") kind("ConsoleApp") language("C++") links({ - "gflags", "xenia-base", "xenia-vfs", }) defines({}) - includedirs({ - project_root.."/third_party/gflags/src", - }) files({ "vfs_dump.cc", diff --git a/third_party/cpptoml b/third_party/cpptoml new file mode 160000 index 000000000..fededad71 --- /dev/null +++ b/third_party/cpptoml @@ -0,0 +1 @@ +Subproject commit fededad7169e538ca47e11a9ee9251bc361a9a65 diff --git a/third_party/cpptoml.lua b/third_party/cpptoml.lua new file mode 100644 index 000000000..fa6c59059 --- /dev/null +++ b/third_party/cpptoml.lua @@ -0,0 +1,8 @@ +group("third_party") +project("cpptoml") + uuid("1e86cc51-3f8b-476d-9249-3b200424846b") + kind("Utility") + language("C++") + files({ + "cpptoml/include/cpptoml.h", + }) diff --git a/third_party/cxxopts b/third_party/cxxopts new file mode 160000 index 000000000..48e265dc4 --- /dev/null +++ b/third_party/cxxopts @@ -0,0 +1 @@ +Subproject commit 48e265dc4b347d3178e4458de81704e0d88047b2 diff --git a/third_party/cxxopts.lua b/third_party/cxxopts.lua new file mode 100644 index 000000000..d3b3015ce --- /dev/null +++ b/third_party/cxxopts.lua @@ -0,0 +1,9 @@ +group("third_party") +project("cxxopts") + uuid("8b68cbe8-2da4-4f28-be14-9352eafa3168") + kind("Utility") + language("C++") + files({ + "cxxopts/include/cxxopts.hpp", + }) + warnings("Off") diff --git a/third_party/gflags b/third_party/gflags deleted file mode 160000 index 78b15171a..000000000 --- a/third_party/gflags +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 78b15171a7fce5815df58a919ab593ce80222028 diff --git a/third_party/gflags.lua b/third_party/gflags.lua deleted file mode 100644 index edb9a4eb6..000000000 --- a/third_party/gflags.lua +++ /dev/null @@ -1,41 +0,0 @@ -group("third_party") -project("gflags") - uuid("e319da87-75ed-4517-8f65-bd25e9cc02a3") - kind("StaticLib") - language("C++") - - -- These win32-specific overrides must come before others. - filter("platforms:Windows") - defines({ - "PATH_SEPARATOR=%%27\\\\%%27", - }) - includedirs({ - "gflags/src/windows", - }) - filter({}) - - defines({ - "GFLAGS_DLL_DECL=", - "GFLAGS_DLL_DEFINE_FLAG=", - "GFLAGS_DLL_DECLARE_FLAG=", - "_LIB", - }) - includedirs({ - "gflags/src", - }) - files({ - "gflags/src/gflags.cc", - "gflags/src/gflags_completions.cc", - "gflags/src/gflags_reporting.cc", - "gflags/src/mutex.h", - "gflags/src/util.h", - }) - filter("platforms:Windows") - files({ - "gflags/src/windows/config.h", - "gflags/src/windows/gflags/gflags.h", - "gflags/src/windows/gflags/gflags_completions.h", - "gflags/src/windows/gflags/gflags_declare.h", - "gflags/src/windows/port.cc", - "gflags/src/windows/port.h", - }) diff --git a/tools/build/scripts/test_suite.lua b/tools/build/scripts/test_suite.lua index 78e46aa4f..096968f7c 100644 --- a/tools/build/scripts/test_suite.lua +++ b/tools/build/scripts/test_suite.lua @@ -25,7 +25,6 @@ local function combined_test_suite(test_suite_name, project_root, base_path, con project_root.."/"..build_bin, })) links(merge_arrays(config["links"], { - "gflags", })) files({ project_root.."/"..build_tools_src.."/test_suite_main.cc", @@ -50,7 +49,6 @@ local function split_test_suite(test_suite_name, project_root, base_path, config project_root.."/"..build_bin, })) links(merge_arrays(config["links"], { - "gflags", })) files({ project_root.."/"..build_tools_src.."/test_suite_main.cc", diff --git a/tools/build/src/test_suite_main.cc b/tools/build/src/test_suite_main.cc index a0531e95a..8cb039e4f 100644 --- a/tools/build/src/test_suite_main.cc +++ b/tools/build/src/test_suite_main.cc @@ -7,8 +7,6 @@ ****************************************************************************** */ -#include - #include #include #include @@ -17,6 +15,7 @@ #define CATCH_CONFIG_RUNNER #include "third_party/catch/include/catch.hpp" +#include "xenia/base/cvar.h" namespace xe { @@ -24,16 +23,11 @@ bool has_console_attached() { return true; } // Used in console mode apps; automatically picked based on subsystem. int Main(int argc, char* argv[]) { - google::SetUsageMessage(std::string("usage: ...")); - google::SetVersionString("1.0"); - - // Parse flags; this may delete some of them. - google::ParseCommandLineFlags(&argc, &argv, true); + cvar::ParseLaunchArguments(argc, argv); // Run Catch. int result = Catch::Session().run(argc, argv); - google::ShutDownCommandLineFlags(); return result; } diff --git a/xenia-build b/xenia-build index 804573edf..0fe8628d9 100755 --- a/xenia-build +++ b/xenia-build @@ -598,7 +598,7 @@ class BaseBuildCommand(Command): '--no_premake', action='store_true', help='Skips running premake before building.') self.parser.add_argument( - '-j', default=0, type=int, help='Number of parallel threads') + '-j', default=4, type=int, help='Number of parallel threads') def execute(self, args, pass_args, cwd): if not args['no_premake']: