From 29e5febab0d3c58c61c4240f24076bcd6e317d26 Mon Sep 17 00:00:00 2001 From: Sude Date: Tue, 23 May 2017 16:44:27 +0300 Subject: [PATCH] Galaxy: Support selecting platform architecture Add option --galaxy-arch to select architecture. Supports selecting platform architecture when "osBitness" is set for depot. If "osBitness" is not set in API response then assume that we want to download the files from depot. --- include/config.h | 1 + include/downloader.h | 2 +- include/globalconstants.h | 10 ++++++++++ include/util.h | 2 +- main.cpp | 15 ++++++++++++++- src/downloader.cpp | 36 ++++++++++++++++++++++++++++++++---- src/util.cpp | 4 ++-- 7 files changed, 61 insertions(+), 9 deletions(-) diff --git a/include/config.h b/include/config.h index 5f00b5b..b0750de 100644 --- a/include/config.h +++ b/include/config.h @@ -36,6 +36,7 @@ struct DownloadConfig unsigned int iInclude; unsigned int iGalaxyPlatform; unsigned int iGalaxyLanguage; + unsigned int iGalaxyArch; bool bRemoteXML; bool bCover; diff --git a/include/downloader.h b/include/downloader.h index 3d91a5c..aae9acc 100644 --- a/include/downloader.h +++ b/include/downloader.h @@ -90,7 +90,7 @@ class Downloader std::deque< std::pair > TimeAndSize; void saveGalaxyJSON(); - void galaxyInstallGame(const std::string& product_id, int build_index = -1); + void galaxyInstallGame(const std::string& product_id, int build_index = -1, const unsigned int& iGalaxyArch = GlobalConstants::ARCH_X64); void galaxyShowBuilds(const std::string& product_id, int build_index = -1); protected: private: diff --git a/include/globalconstants.h b/include/globalconstants.h index 6835dc4..5750d61 100644 --- a/include/globalconstants.h +++ b/include/globalconstants.h @@ -83,6 +83,16 @@ namespace GlobalConstants { PLATFORM_MAC, "mac", "Mac" , "m|mac|osx" }, { PLATFORM_LINUX, "linux", "Linux" , "l|lin|linux" } }; + + // Galaxy platform arch + const unsigned int ARCH_X86 = 1 << 0; + const unsigned int ARCH_X64 = 1 << 1; + + const std::vector GALAXY_ARCHS = + { + { ARCH_X86, "32", "32-bit", "32|x86|32bit|32-bit" }, + { ARCH_X64, "64", "64-bit", "64|x64|64bit|64-bit" } + }; } #endif // GLOBALCONSTANTS_H_INCLUDED diff --git a/include/util.h b/include/util.h index b31ea1a..c3ee2cc 100644 --- a/include/util.h +++ b/include/util.h @@ -66,7 +66,7 @@ namespace Util std::string getConfigHome(); std::string getCacheHome(); std::vector tokenize(const std::string& str, const std::string& separator = ","); - unsigned int getOptionValue(const std::string& str, const std::vector& options); + unsigned int getOptionValue(const std::string& str, const std::vector& options, const bool& bAllowStringToIntConversion = true); std::string getOptionNameString(const unsigned int& value, const std::vector& options); void parseOptionString(const std::string &option_string, std::vector &priority, unsigned int &type, const std::vector& options); std::string getLocalFileHash(const std::string& xml_dir, const std::string& filepath, const std::string& gamename = std::string()); diff --git a/main.cpp b/main.cpp index 3298781..d47d2b7 100644 --- a/main.cpp +++ b/main.cpp @@ -100,6 +100,13 @@ int main(int argc, char *argv[]) galaxy_language_text += GlobalConstants::LANGUAGES[i].str + " = " + GlobalConstants::LANGUAGES[i].regexp + "|" + std::to_string(GlobalConstants::LANGUAGES[i].id) + "\n"; } + // Create help text for --galaxy-arch option + std::string galaxy_arch_text = "Select architecture\n"; + for (unsigned int i = 0; i < GlobalConstants::GALAXY_ARCHS.size(); ++i) + { + galaxy_arch_text += GlobalConstants::GALAXY_ARCHS[i].str + " = " + GlobalConstants::GALAXY_ARCHS[i].regexp + "|" + std::to_string(GlobalConstants::GALAXY_ARCHS[i].id) + "\n"; + } + // Create help text for --check-orphans std::string orphans_regex_default = ".*\\.(zip|exe|bin|dmg|old|deb|tar\\.gz|pkg|sh)$"; // Limit to files with these extensions (".old" is for renamed older version files) std::string check_orphans_text = "Check for orphaned files (files found on local filesystem that are not found on GOG servers). Sets regular expression filter (Perl syntax) for files to check. If no argument is given then the regex defaults to '" + orphans_regex_default + "'"; @@ -145,6 +152,7 @@ int main(int argc, char *argv[]) std::string sExcludeOptions; std::string sGalaxyPlatform; std::string sGalaxyLanguage; + std::string sGalaxyArch; Globals::globalConfig.bReport = false; // Commandline options (no config file) options_cli_no_cfg.add_options() @@ -220,6 +228,7 @@ int main(int argc, char *argv[]) ("galaxy-show-builds", bpo::value(&galaxy_product_id_show_builds)->default_value(""), "Show game builds using product id") ("galaxy-platform", bpo::value(&sGalaxyPlatform)->default_value("w"), galaxy_platform_text.c_str()) ("galaxy-language", bpo::value(&sGalaxyLanguage)->default_value("en"), galaxy_language_text.c_str()) + ("galaxy-arch", bpo::value(&sGalaxyArch)->default_value("x64"), galaxy_arch_text.c_str()) ("login-email", bpo::value(&Globals::globalConfig.sEmail)->default_value(""), "login email") ("login-password", bpo::value(&Globals::globalConfig.sPassword)->default_value(""), "login password") ; @@ -450,6 +459,10 @@ int main(int argc, char *argv[]) Globals::globalConfig.dlConf.iGalaxyPlatform = Util::getOptionValue(sGalaxyPlatform, GlobalConstants::PLATFORMS); Globals::globalConfig.dlConf.iGalaxyLanguage = Util::getOptionValue(sGalaxyLanguage, GlobalConstants::LANGUAGES); + Globals::globalConfig.dlConf.iGalaxyArch = Util::getOptionValue(sGalaxyArch, GlobalConstants::GALAXY_ARCHS, false); + + if (Globals::globalConfig.dlConf.iGalaxyArch == 0 || Globals::globalConfig.dlConf.iGalaxyArch == Util::getOptionValue("all", GlobalConstants::GALAXY_ARCHS, false)) + Globals::globalConfig.dlConf.iGalaxyArch = GlobalConstants::ARCH_X64; unsigned int include_value = 0; unsigned int exclude_value = 0; @@ -740,7 +753,7 @@ int main(int argc, char *argv[]) { build_index = std::stoi(tokens[1]); } - downloader.galaxyInstallGame(product_id, build_index); + downloader.galaxyInstallGame(product_id, build_index, Globals::globalConfig.dlConf.iGalaxyArch); } else { diff --git a/src/downloader.cpp b/src/downloader.cpp index 66fc36e..735ac58 100644 --- a/src/downloader.cpp +++ b/src/downloader.cpp @@ -3502,7 +3502,7 @@ void Downloader::saveGalaxyJSON() } } -void Downloader::galaxyInstallGame(const std::string& product_id, int build_index) +void Downloader::galaxyInstallGame(const std::string& product_id, int build_index, const unsigned int& iGalaxyArch) { if (build_index < 0) build_index = 0; @@ -3527,6 +3527,16 @@ void Downloader::galaxyInstallGame(const std::string& product_id, int build_inde } } + std::string sGalaxyArch = "64"; + for (unsigned int i = 0; i < GlobalConstants::GALAXY_ARCHS.size(); ++i) + { + if (GlobalConstants::GALAXY_ARCHS[i].id == iGalaxyArch) + { + sGalaxyArch = GlobalConstants::GALAXY_ARCHS[i].code; + break; + } + } + Json::Value json = gogGalaxy->getProductBuilds(product_id, sPlatform); // JSON is empty and platform is Linux. Most likely cause is that Galaxy API doesn't have Linux support @@ -3552,10 +3562,13 @@ void Downloader::galaxyInstallGame(const std::string& product_id, int build_inde if (install_directory.empty()) install_directory = product_id; + std::string install_path = Globals::globalConfig.dirConf.sDirectory + install_directory; + std::vector items; for (unsigned int i = 0; i < json["depots"].size(); ++i) { bool bSelectedLanguage = false; + bool bSelectedArch = false; for (unsigned int j = 0; j < json["depots"][i]["languages"].size(); ++j) { std::string language = json["depots"][i]["languages"][j].asString(); @@ -3563,7 +3576,22 @@ void Downloader::galaxyInstallGame(const std::string& product_id, int build_inde bSelectedLanguage = true; } - if (!bSelectedLanguage) + if (json["depots"][i].isMember("osBitness")) + { + for (unsigned int j = 0; j < json["depots"][i]["osBitness"].size(); ++j) + { + std::string osBitness = json["depots"][i]["osBitness"][j].asString(); + if (osBitness == "*" || osBitness == sGalaxyArch) + bSelectedArch = true; + } + } + else + { + // No osBitness found, assume that we want to download this depot + bSelectedArch = true; + } + + if (!bSelectedLanguage || !bSelectedArch) continue; std::string depotHash = json["depots"][i]["manifest"].asString(); @@ -3595,12 +3623,12 @@ void Downloader::galaxyInstallGame(const std::string& product_id, int build_inde double totalSizeMB = static_cast(totalSize)/1024/1024; std::cout << game_title << std::endl; - std::cout << "Files: " << items.size() - 1 << std::endl; + std::cout << "Files: " << items.size() << std::endl; std::cout << "Total size installed: " << totalSizeMB << " MB" << std::endl; for (unsigned int i = 0; i < items.size(); ++i) { - boost::filesystem::path path = Globals::globalConfig.dirConf.sDirectory + install_directory + "/" + items[i].path; + boost::filesystem::path path = install_path + "/" + items[i].path; // Check that directory exists and create it boost::filesystem::path directory = path.parent_path(); diff --git a/src/util.cpp b/src/util.cpp index 9f11554..416a69b 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -482,7 +482,7 @@ std::vector Util::tokenize(const std::string& str, const std::strin return tokens; } -unsigned int Util::getOptionValue(const std::string& str, const std::vector& options) +unsigned int Util::getOptionValue(const std::string& str, const std::vector& options, const bool& bAllowStringToIntConversion) { unsigned int value = 0; boost::regex expression("^[+-]?\\d+$", boost::regex::perl); @@ -491,7 +491,7 @@ unsigned int Util::getOptionValue(const std::string& str, const std::vector