From 836f7327db88bc39ceebc35ddc682532f74d3edb Mon Sep 17 00:00:00 2001 From: Tyler Wilding Date: Sat, 20 Apr 2024 23:38:05 -0400 Subject: [PATCH] integ test commit --- common/util/FileUtil.cpp | 93 +++++++++++++++++++----- common/util/FileUtil.h | 5 ++ decompiler/ObjectFile/ObjectFileDB.h | 4 +- decompiler/extractor/extractor_util.cpp | 5 ++ decompiler/extractor/main.cpp | 15 +++- decompiler/util/DecompilerTypeSystem.cpp | 2 +- game/main.cpp | 20 +++++ game/system/hid/devices/keyboard.h | 6 +- game/system/hid/devices/mouse.h | 6 +- goalc/build_level/jak1/build_level.cpp | 15 +--- goalc/build_level/jak2/build_level.cpp | 15 +--- lsp/state/workspace.cpp | 6 +- 12 files changed, 137 insertions(+), 55 deletions(-) diff --git a/common/util/FileUtil.cpp b/common/util/FileUtil.cpp index 212419544d..7b588189ab 100644 --- a/common/util/FileUtil.cpp +++ b/common/util/FileUtil.cpp @@ -57,6 +57,14 @@ fs::path get_user_home_dir() { #endif } +struct { + bool initialized = false; + fs::path path_to_data_folder; + fs::path user_config_dir_override = ""; + // by default - if the config dir is overridden, we don't use the default save location + bool use_overridden_config_dir_for_saves = true; +} g_file_path_info; + fs::path get_user_config_dir() { fs::path config_base_path; #ifdef _WIN32 @@ -80,35 +88,53 @@ fs::path get_user_config_dir() { fs::path get_user_settings_dir(GameVersion game_version) { auto game_version_name = game_version_names[game_version]; - return get_user_config_dir() / game_version_name / "settings"; + auto config_dir = get_user_config_dir(); + if (!g_file_path_info.user_config_dir_override.empty()) { + config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL"; + } + return config_dir / game_version_name / "settings"; } fs::path get_user_memcard_dir(GameVersion game_version) { auto game_version_name = game_version_names[game_version]; - return get_user_config_dir() / game_version_name / "saves"; + auto config_dir = get_user_config_dir(); + if (!g_file_path_info.user_config_dir_override.empty() && + g_file_path_info.use_overridden_config_dir_for_saves) { + config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL"; + } + return config_dir / game_version_name / "saves"; } fs::path get_user_screenshots_dir(GameVersion game_version) { auto game_version_name = game_version_names[game_version]; - return get_user_config_dir() / game_version_name / "screenshots"; + auto config_dir = get_user_config_dir(); + if (!g_file_path_info.user_config_dir_override.empty()) { + config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL"; + } + return config_dir / game_version_name / "screenshots"; } fs::path get_user_misc_dir(GameVersion game_version) { auto game_version_name = game_version_names[game_version]; - return get_user_config_dir() / game_version_name / "misc"; + auto config_dir = get_user_config_dir(); + if (!g_file_path_info.user_config_dir_override.empty()) { + config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL"; + } + return config_dir / game_version_name / "misc"; } fs::path get_user_features_dir(GameVersion game_version) { auto game_version_name = game_version_names[game_version]; - auto path = get_user_config_dir() / game_version_name / "features"; + auto config_dir = get_user_config_dir(); + if (!g_file_path_info.user_config_dir_override.empty()) { + config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL"; + } + auto path = config_dir / game_version_name / "features"; file_util::create_dir_if_needed(path); return path; } -struct { - bool initialized = false; - fs::path path_to_data; -} gFilePathInfo; +fs::path g_iso_data_directory = ""; /*! * Get the path to the current executable. @@ -171,29 +197,30 @@ std::optional try_get_data_dir() { } bool setup_project_path(std::optional project_path_override) { - if (gFilePathInfo.initialized) { + if (g_file_path_info.initialized) { return true; } if (project_path_override) { - gFilePathInfo.path_to_data = fs::absolute(project_path_override.value()); - gFilePathInfo.initialized = true; - lg::info("Using explicitly set project path: {}", gFilePathInfo.path_to_data.string()); + g_file_path_info.path_to_data_folder = fs::absolute(project_path_override.value()); + g_file_path_info.initialized = true; + lg::info("Using explicitly set project path: {}", + g_file_path_info.path_to_data_folder.string()); return true; } auto data_path = try_get_data_dir(); if (data_path) { - gFilePathInfo.path_to_data = *data_path; - gFilePathInfo.initialized = true; + g_file_path_info.path_to_data_folder = *data_path; + g_file_path_info.initialized = true; lg::info("Using data path: {}", data_path->string()); return true; } auto development_repo_path = try_get_jak_project_path(); if (development_repo_path) { - gFilePathInfo.path_to_data = *development_repo_path; - gFilePathInfo.initialized = true; + g_file_path_info.path_to_data_folder = *development_repo_path; + g_file_path_info.initialized = true; lg::info("Using development repo path: {}", *development_repo_path); return true; } @@ -202,9 +229,37 @@ bool setup_project_path(std::optional project_path_override) { return false; } +void override_user_config_dir(fs::path user_config_dir_override, + bool use_overridden_config_dir_for_saves) { + g_file_path_info.user_config_dir_override = user_config_dir_override; + g_file_path_info.use_overridden_config_dir_for_saves = use_overridden_config_dir_for_saves; +} + fs::path get_jak_project_dir() { - ASSERT(gFilePathInfo.initialized); - return gFilePathInfo.path_to_data; + ASSERT(g_file_path_info.initialized); + return g_file_path_info.path_to_data_folder; +} + +fs::path get_iso_dir_for_game(GameVersion game_version) { + if (!g_iso_data_directory.empty()) { + return g_iso_data_directory; + } + // Find the location based on the game version + std::string expected_subdir = "jak1"; + if (game_version == GameVersion::Jak2) { + expected_subdir = "jak2"; + } else if (game_version == GameVersion::Jak3) { + expected_subdir = "jak3"; + } + const auto temp_dir = get_jak_project_dir() / "iso_data" / expected_subdir; + if (fs::exists(temp_dir)) { + g_iso_data_directory = temp_dir; + } + return g_iso_data_directory; +} + +void set_iso_data_dir(const fs::path& directory) { + g_iso_data_directory = directory; } std::string get_file_path(const std::vector& input) { diff --git a/common/util/FileUtil.h b/common/util/FileUtil.h index 82cd89b397..11ffc894a8 100644 --- a/common/util/FileUtil.h +++ b/common/util/FileUtil.h @@ -35,12 +35,17 @@ fs::path get_user_screenshots_dir(GameVersion game_version); fs::path get_user_misc_dir(GameVersion game_version); fs::path get_user_features_dir(GameVersion game_version); fs::path get_jak_project_dir(); +fs::path get_iso_dir_for_game(GameVersion game_version); +void set_iso_data_dir(const fs::path& directory); bool create_dir_if_needed(const fs::path& path); bool create_dir_if_needed_for_file(const std::string& path); bool create_dir_if_needed_for_file(const fs::path& path); +std::string get_current_executable_path(); std::optional try_get_project_path_from_path(const std::string& path); bool setup_project_path(std::optional project_path_override); +void override_user_config_dir(fs::path user_config_dir_override, + bool use_overridden_config_dir_for_saves); std::string get_file_path(const std::vector& path); void write_binary_file(const std::string& name, const void* data, size_t size); void write_binary_file(const fs::path& name, const void* data, size_t size); diff --git a/decompiler/ObjectFile/ObjectFileDB.h b/decompiler/ObjectFile/ObjectFileDB.h index 0811bafb3c..574e6e28a8 100644 --- a/decompiler/ObjectFile/ObjectFileDB.h +++ b/decompiler/ObjectFile/ObjectFileDB.h @@ -332,7 +332,7 @@ class ObjectFileDB { void for_each_function_def_order(Func f) { for_each_obj([&](ObjectFileData& data) { for (int i = 0; i < int(data.linked_data.segments); i++) { - int fn = 0; + [[maybe_unused]] int fn = 0; for (size_t j = data.linked_data.functions_by_seg.at(i).size(); j-- > 0;) { f(data.linked_data.functions_by_seg.at(i).at(j), i, data); fn++; @@ -355,7 +355,7 @@ class ObjectFileDB { template void for_each_function_in_seg(int seg, Func f) { for_each_obj([&](ObjectFileData& data) { - int fn = 0; + [[maybe_unused]] int fn = 0; if (data.linked_data.segments == 3) { for (size_t j = data.linked_data.functions_by_seg.at(seg).size(); j-- > 0;) { f(data.linked_data.functions_by_seg.at(seg).at(j), data); diff --git a/decompiler/extractor/extractor_util.cpp b/decompiler/extractor/extractor_util.cpp index 73de70463d..d3f58eb54d 100644 --- a/decompiler/extractor/extractor_util.cpp +++ b/decompiler/extractor/extractor_util.cpp @@ -267,6 +267,11 @@ std::tuple calculate_extraction_hash(const fs::path& extracted_is int filec = 0; for (auto const& dir_entry : fs::recursive_directory_iterator(extracted_iso_path)) { if (dir_entry.is_regular_file()) { + // skip the `buildinfo.json` file, we make that -- not relevant! + if (dir_entry.path().filename() == "buildinfo.json") { + lg::warn("skipping buildinfo.json, that is a file our tools generate"); + continue; + } auto buffer = file_util::read_binary_file(dir_entry.path().string()); auto hash = XXH64(buffer.data(), buffer.size(), 0); combined_hash ^= hash; diff --git a/decompiler/extractor/main.cpp b/decompiler/extractor/main.cpp index cbb31c45b0..d22adff5d6 100644 --- a/decompiler/extractor/main.cpp +++ b/decompiler/extractor/main.cpp @@ -102,7 +102,10 @@ std::tuple, ExtractorErrorCode> validate( }; } -void decompile(const fs::path& iso_data_path, const std::string& data_subfolder) { +// TODO - remove code duplication, most of this is copying what happens in decompiler's `main.cpp` +void decompile(const fs::path& iso_data_path, + const std::string& data_subfolder, + const std::string& config_override) { using namespace decompiler; // Determine which config to use from the database @@ -111,7 +114,7 @@ void decompile(const fs::path& iso_data_path, const std::string& data_subfolder) Config config = read_config_file(file_util::get_jak_project_dir() / "decompiler" / "config" / version_info.game_name / fmt::format("{}_config.jsonc", version_info.game_name), - version_info.decomp_config_version); + version_info.decomp_config_version, config_override); std::vector dgos, objs, tex_strs, art_strs; @@ -220,6 +223,8 @@ ExtractorErrorCode compile(const fs::path& iso_data_path, const std::string& dat Compiler compiler(game_name_to_version(version_info.game_name)); compiler.make_system().set_constant("*iso-data*", absolute(iso_data_path).string()); compiler.make_system().set_constant("*use-iso-data-path*", true); + file_util::set_iso_data_dir(absolute(iso_data_path)); + lg::info("set iso_data_dir to {}", absolute(iso_data_path).string()); int flags = 0; for (const auto& flag : version_info.flags) { @@ -265,6 +270,7 @@ int main(int argc, char** argv) { bool flag_play = false; bool flag_folder = false; std::string game_name = "jak1"; + std::string decomp_config_override = "{}"; lg::initialize(); @@ -275,6 +281,9 @@ int main(int argc, char** argv) { app.add_option("--proj-path", project_path_override, "Explicitly set the location of the 'data/' folder"); app.add_option("-g,--game", game_name, "Specify the game name, defaults to 'jak1'"); + app.add_option( + "--decomp-config-override", decomp_config_override, + "JSON provided will be merged with the decompiler config, use to override options"); app.add_flag("-a,--all", flag_runall, "Run all steps, from extraction to playing the game"); app.add_flag("-e,--extract", flag_extract, "Extract the ISO"); app.add_flag("-v,--validate", flag_fail_on_validation, @@ -423,7 +432,7 @@ int main(int argc, char** argv) { if (flag_decompile) { try { - decompile(iso_data_path, data_subfolder); + decompile(iso_data_path, data_subfolder, decomp_config_override); } catch (std::exception& e) { lg::error("Error during decompile: {}", e.what()); return static_cast(ExtractorErrorCode::DECOMPILATION_GENERIC_ERROR); diff --git a/decompiler/util/DecompilerTypeSystem.cpp b/decompiler/util/DecompilerTypeSystem.cpp index 0b9a701199..d576201623 100644 --- a/decompiler/util/DecompilerTypeSystem.cpp +++ b/decompiler/util/DecompilerTypeSystem.cpp @@ -2,12 +2,12 @@ #include "TP_Type.h" +#include "common/goos/Printer.h" #include "common/goos/Reader.h" #include "common/log/log.h" #include "common/type_system/defenum.h" #include "common/type_system/deftype.h" #include "common/util/string_util.h" -#include #include "decompiler/Disasm/Register.h" diff --git a/game/main.cpp b/game/main.cpp index edff28b3e1..eed4b22bf2 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -96,11 +96,14 @@ int main(int argc, char** argv) { bool disable_avx2 = false; bool disable_display = false; bool enable_profiling = false; + bool enable_portable = false; + bool disable_save_location_override = false; std::string profile_until_event = ""; std::string gpu_test = ""; std::string gpu_test_out_path = ""; int port_number = -1; fs::path project_path_override; + fs::path user_config_dir_override; std::vector game_args; CLI::App app{"OpenGOAL Game Runtime"}; app.add_flag("--version", show_version, "Display the built revision"); @@ -112,6 +115,12 @@ int main(int argc, char** argv) { app.add_flag("--no-avx2", disable_avx2, "Disable AVX2 for testing"); app.add_flag("--no-display", disable_display, "Disable video display"); app.add_flag("--profile", enable_profiling, "Enables profiling immediately from startup"); + app.add_flag("--portable", enable_portable, + "Save settings and saves relative to the game's executable, takes precedence over " + "--config-path"); + app.add_flag("--disable_save_location_override", disable_save_location_override, + "If --config-path is provided along with this flag, saves will still be loaded and " + "stored to the default location"); app.add_option("--profile-until-event", profile_until_event, "Stops recording profile events once an event with this name is seen"); app.add_option("--gpu-test", gpu_test, @@ -120,6 +129,8 @@ int main(int argc, char** argv) { "Where to store the gpu test result file"); app.add_option("--proj-path", project_path_override, "Specify the location of the 'data/' folder"); + app.add_option("--config-path", user_config_dir_override, + "Override the location where all user configuration and saves are saved"); app.footer(game_arg_documentation()); app.add_option("Game Args", game_args, "Remaining arguments (after '--') that are passed-through to the game itself"); @@ -127,6 +138,15 @@ int main(int argc, char** argv) { app.allow_extras(); CLI11_PARSE(app, argc, argv); + // Override the user's config dir, potentially (either because it was explicitly provided + // or because it's portable mode) + if (enable_portable) { + user_config_dir_override = file_util::get_current_executable_path(); + } + if (!user_config_dir_override.empty()) { + file_util::override_user_config_dir(user_config_dir_override, !disable_save_location_override); + } + if (show_version) { lg::print("{}", build_revision()); return 0; diff --git a/game/system/hid/devices/keyboard.h b/game/system/hid/devices/keyboard.h index 32fa80c67b..117358d876 100644 --- a/game/system/hid/devices/keyboard.h +++ b/game/system/hid/devices/keyboard.h @@ -31,9 +31,11 @@ class KeyboardDevice : public InputDevice { const CommandBindingGroups& commands, std::shared_ptr data, std::optional& bind_assignment) override; - void close_device() override{ - // there is nothing to close + // clang-format off + void close_device() override { + // there is nothing to close }; + // clang-format on private: std::vector m_active_actions = {}; diff --git a/game/system/hid/devices/mouse.h b/game/system/hid/devices/mouse.h index a1159b86fe..1ff60ada96 100644 --- a/game/system/hid/devices/mouse.h +++ b/game/system/hid/devices/mouse.h @@ -31,9 +31,11 @@ class MouseDevice : public InputDevice { const CommandBindingGroups& commands, std::shared_ptr data, std::optional& bind_assignment) override; - void close_device() override{ - // there is nothing to close + // clang-format off + void close_device() override { + // there is nothing to close }; + // clang-format on void enable_relative_mode(const bool enable); void enable_camera_control(const bool enable); diff --git a/goalc/build_level/jak1/build_level.cpp b/goalc/build_level/jak1/build_level.cpp index 15df0e3d70..eb0477c05e 100644 --- a/goalc/build_level/jak1/build_level.cpp +++ b/goalc/build_level/jak1/build_level.cpp @@ -104,18 +104,9 @@ bool run_build_level(const std::string& input_file, // TODO remove hardcoded config settings if ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) || (level_json.contains("textures") && !level_json.at("textures").empty())) { - fs::path iso_folder = ""; lg::info("Looking for ISO path..."); - // TODO - add to file_util - for (const auto& entry : - fs::directory_iterator(file_util::get_jak_project_dir() / "iso_data")) { - // TODO - hard-coded to jak 1 - if (entry.is_directory() && - entry.path().filename().string().find("jak1") != std::string::npos) { - lg::info("Found ISO path: {}", entry.path().string()); - iso_folder = entry.path(); - } - } + const auto iso_folder = file_util::get_iso_dir_for_game(GameVersion::Jak1); + lg::info("Found ISO path: {}", iso_folder.string()); if (iso_folder.empty() || !fs::exists(iso_folder)) { lg::warn("Could not locate ISO path!"); @@ -217,4 +208,4 @@ bool run_build_level(const std::string& input_file, return true; } -} // namespace jak1 \ No newline at end of file +} // namespace jak1 diff --git a/goalc/build_level/jak2/build_level.cpp b/goalc/build_level/jak2/build_level.cpp index 97a9e4c691..c92b2f4957 100644 --- a/goalc/build_level/jak2/build_level.cpp +++ b/goalc/build_level/jak2/build_level.cpp @@ -91,18 +91,9 @@ bool run_build_level(const std::string& input_file, // TODO remove hardcoded config settings if ((level_json.contains("art_groups") && !level_json.at("art_groups").empty()) || (level_json.contains("textures") && !level_json.at("textures").empty())) { - fs::path iso_folder = ""; lg::info("Looking for ISO path..."); - // TODO - add to file_util - for (const auto& entry : - fs::directory_iterator(file_util::get_jak_project_dir() / "iso_data")) { - // TODO - hard-coded to jak 2 - if (entry.is_directory() && - entry.path().filename().string().find("jak2") != std::string::npos) { - lg::info("Found ISO path: {}", entry.path().string()); - iso_folder = entry.path(); - } - } + const auto iso_folder = file_util::get_iso_dir_for_game(GameVersion::Jak2); + lg::info("Found ISO path: {}", iso_folder.string()); if (iso_folder.empty() || !fs::exists(iso_folder)) { lg::warn("Could not locate ISO path!"); @@ -203,4 +194,4 @@ bool run_build_level(const std::string& input_file, return true; } -} // namespace jak2 \ No newline at end of file +} // namespace jak2 diff --git a/lsp/state/workspace.cpp b/lsp/state/workspace.cpp index 4ea3bc4c3b..4559fd2f5a 100644 --- a/lsp/state/workspace.cpp +++ b/lsp/state/workspace.cpp @@ -379,9 +379,11 @@ void Workspace::tracked_file_will_save(const LSPSpec::DocumentUri& file_uri) { } } -void Workspace::update_global_index(const GameVersion game_version){ - // TODO - project wide indexing potentially (ie. finding references) +// clang-format off +void Workspace::update_global_index(const GameVersion game_version) { + // TODO - project wide indexing potentially (ie. finding references) }; +// clang-format on void Workspace::stop_tracking_file(const LSPSpec::DocumentUri& file_uri) { m_tracked_ir_files.erase(file_uri);