diff --git a/Makefile b/Makefile index b1b7888..3273ca9 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ DATA := data INCLUDES := include lib/zipper/include /lib/borealis/library/include/borealis/extern/nlohmann APP_TITLE := All-in-One Switch Updater APP_AUTHOR := HamletDuFromage -APP_VERSION := 2.16.1 +APP_VERSION := 2.16.2 TARGET := $(notdir $(CURDIR)) ROMFS := resources diff --git a/include/extract.hpp b/include/extract.hpp index 19f44d8..2dc2643 100644 --- a/include/extract.hpp +++ b/include/extract.hpp @@ -31,8 +31,8 @@ namespace extract { std::vector getInstalledTitlesNs(); std::vector excludeTitles(const std::string& path, const std::vector& listedTitles); void writeTitlesToFile(const std::set& titles, const std::string& path); - void extractCheats(const std::string& zipPath, std::vector titles, CFW cfw, bool credits = false); - void extractAllCheats(const std::string& zipPath, CFW cfw); + void extractCheats(const std::string& zipPath, const std::vector& titles, CFW cfw, const std::string& version, bool extractAll = false); + void extractAllCheats(const std::string& zipPath, CFW cfw, const std::string& version); void removeCheats(); void removeOrphanedCheats(); bool removeCheatsDirectory(const std::string& entry); diff --git a/include/utils.hpp b/include/utils.hpp index 4d306ea..d0a23ca 100644 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -26,7 +26,7 @@ namespace util { bool isArchive(const std::string& path); void downloadArchive(const std::string& url, contentType type); void downloadArchive(const std::string& url, contentType type, long& status_code); - void extractArchive(contentType type, const std::string& tag = "0"); + void extractArchive(contentType type, const std::string& version = ""); std::string formatListItemTitle(const std::string& str, size_t maxScore = 140); std::string formatApplicationId(u64 ApplicationId); std::vector fetchPayloads(); @@ -36,8 +36,9 @@ namespace util { int showDialogBox(const std::string& text, const std::string& opt1, const std::string& opt2); std::string getLatestTag(const std::string& url); std::string downloadFileToString(const std::string& url); - void saveVersion(const std::string& version, const std::string& path); - std::string readVersion(const std::string& path); + std::string getCheatsVersion(); + void saveToFile(const std::string& text, const std::string& path); + std::string readFile(const std::string& path); bool isErista(); void removeSysmodulesFlags(const std::string& directory); std::string lowerCase(const std::string& str); diff --git a/source/changelog_page.cpp b/source/changelog_page.cpp index ac894cb..0544867 100644 --- a/source/changelog_page.cpp +++ b/source/changelog_page.cpp @@ -217,6 +217,9 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) verTitles.push_back("v2.16.1"); changes.push_back("\uE016 Updated Japanese localisation (https://github.com/yyoossk).\n\uE016 Updated German localisation (https://github.com/MSco).\n\uE016 Added ability to manually launch aiosu_rcm.bin."); + verTitles.push_back("v2.16.2"); + changes.push_back("\uE016 Allow offline extraction of cheats.\n\uE016 Fixed extraction of the the complete cheat archive.\n\uE016 Fixed display bug for cheats extraction."); + for (int i = verTitles.size() - 1; i >= 0; i--) { listItem = new brls::ListItem(verTitles[i]); change = changes[i]; diff --git a/source/cheats_page.cpp b/source/cheats_page.cpp index 12f40bb..1d7e646 100644 --- a/source/cheats_page.cpp +++ b/source/cheats_page.cpp @@ -53,31 +53,22 @@ CheatsPage::CheatsPage() : AppletFrame(true, true) }); list->addView(item); - std::string cheatsVer = util::downloadFileToString(CHEATS_URL_VERSION); + std::string cheatsVer = util::getCheatsVersion(); if (cheatsVer != "") { item = new brls::ListItem("menus/cheats/dl_all"_i18n); item->getClickEvent()->subscribe([cheatsVer](brls::View* view) { - std::string url; - switch (CurrentCfw::running_cfw) { - case CFW::sxos: - url = CHEATS_URL_TITLES; - break; - case CFW::ams: - url = CHEATS_URL_CONTENTS; - break; - case CFW::rnx: - url = CHEATS_URL_CONTENTS; - break; - } + std::string url = CurrentCfw::running_cfw == CFW::sxos ? CHEATS_URL_TITLES : CHEATS_URL_CONTENTS; std::string text(fmt::format("menus/main/get_cheats"_i18n, cheatsVer) + "menus/common/from"_i18n + url); brls::StagedAppletFrame* stagedFrame = new brls::StagedAppletFrame(); stagedFrame->setTitle("menus/cheats/dl_all"_i18n); stagedFrame->addStage( new ConfirmPage(stagedFrame, text)); + if (cheatsVer != "offline") { + stagedFrame->addStage( + new WorkerPage(stagedFrame, "menus/common/downloading"_i18n, [url]() { util::downloadArchive(url, contentType::cheats); })); + } stagedFrame->addStage( - new WorkerPage(stagedFrame, "menus/common/downloading"_i18n, [url]() { util::downloadArchive(url, contentType::cheats); })); - stagedFrame->addStage( - new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, []() { extract::extractAllCheats(CHEATS_ZIP_PATH, CurrentCfw::running_cfw); })); + new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, [cheatsVer]() { extract::extractAllCheats(CHEATS_ZIP_PATH, CurrentCfw::running_cfw, cheatsVer); })); stagedFrame->addStage( new ConfirmPage(stagedFrame, "menus/common/all_done"_i18n, true)); brls::Application::pushView(stagedFrame); diff --git a/source/extract.cpp b/source/extract.cpp index 771cfaa..5a8fc43 100644 --- a/source/extract.cpp +++ b/source/extract.cpp @@ -13,8 +13,8 @@ #include #include -#include "download.hpp" #include "current_cfw.hpp" +#include "download.hpp" #include "fs.hpp" #include "main_frame.hpp" #include "progress_event.hpp" @@ -180,49 +180,55 @@ namespace extract { return 0; } - void extractCheats(const std::string& zipPath, std::vector titles, CFW cfw, bool credits) + void extractCheats(const std::string& zipPath, const std::vector& titles, CFW cfw, const std::string& version, bool extractAll) { zipper::Unzipper unzipper(zipPath); std::vector entries = unzipper.entries(); int offset = computeOffset(cfw); - ProgressEvent::instance().setTotalSteps(titles.size() + 1); - for (const auto& title : titles) { - if (ProgressEvent::instance().getInterupt()) { - break; + if (!extractAll) { + ProgressEvent::instance().setTotalSteps(titles.size() + 1); + for (const auto& title : titles) { + if (ProgressEvent::instance().getInterupt()) { + break; + } + auto matches = entries | std::views::filter([&title, offset](zipper::ZipEntry entry) { + if ((int)entry.name.size() > offset + 16 + 7) { + return caselessCompare((title.substr(0, 13)), entry.name.substr(offset, 13)) && caselessCompare(entry.name.substr(offset + 16, 7), "/cheats"); + } + else { + return false; + } + }); + for (const auto& match : matches) { + unzipper.extractEntry(match.name); + } + ProgressEvent::instance().incrementStep(1); } - auto matches = entries | std::views::filter([&title, offset](zipper::ZipEntry entry) { - return caselessCompare((title.substr(0, 13)), entry.name.substr(offset, 13)) && caselessCompare(entry.name.substr(offset + 16, 7), "/cheats"); - }); - for (const auto& match : matches) { - unzipper.extractEntry(match.name); + } + else { + ProgressEvent::instance().setTotalSteps(entries.size() + 1); + for (const auto& entry : entries) { + if (ProgressEvent::instance().getInterupt()) { + break; + } + + if ((int)entry.name.size() > offset + 16 + 7 && caselessCompare(entry.name.substr(offset + 16, 7), "/cheats")) { + unzipper.extractEntry(entry.name); + } ProgressEvent::instance().incrementStep(1); } } unzipper.close(); - download::downloadFile(CHEATS_URL_VERSION, CHEATS_VERSION, OFF); + if (version != "offline" && version != "") { + util::saveToFile(version, CHEATS_VERSION); + } ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); } - void extractAllCheats(const std::string& zipPath, CFW cfw) + void extractAllCheats(const std::string& zipPath, CFW cfw, const std::string& version) { - zipper::Unzipper unzipper(zipPath); - std::vector entries = unzipper.entries(); - int offset = computeOffset(cfw); - - ProgressEvent::instance().setTotalSteps(entries.size() + 1); - for (const auto& entry : entries) { - if (ProgressEvent::instance().getInterupt()) { - break; - } - if (((int)entry.name.size() == offset + 16 + 4) && (isBID(entry.name.substr(offset, 16)))) { - unzipper.extractEntry(entry.name); - } - ProgressEvent::instance().incrementStep(1); - } - unzipper.close(); - download::downloadFile(CHEATS_URL_VERSION, CHEATS_VERSION, OFF); - ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); + extractCheats(zipPath, {}, cfw, version, true); } bool isBID(const std::string& bid) diff --git a/source/list_download_tab.cpp b/source/list_download_tab.cpp index 3d509c8..d23cf93 100644 --- a/source/list_download_tab.cpp +++ b/source/list_download_tab.cpp @@ -63,10 +63,10 @@ void ListDownloadTab::createList(contentType type) stagedFrame->setTitle(fmt::format("menus/main/getting"_i18n, contentTypeNames[(int)type].data())); stagedFrame->addStage(new ConfirmPage(stagedFrame, text)); if (type != contentType::payloads) { - if (type != contentType::cheats || this->newCheatsVer != this->currentCheatsVer || !std::filesystem::exists(CHEATS_ZIP_PATH)) { + if (type != contentType::cheats || (this->newCheatsVer != this->currentCheatsVer && this->newCheatsVer != "offline")) { stagedFrame->addStage(new WorkerPage(stagedFrame, "menus/common/downloading"_i18n, [this, type, url]() { util::downloadArchive(url, type); })); } - stagedFrame->addStage(new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, [this, type]() { util::extractArchive(type); })); + stagedFrame->addStage(new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, [this, type]() { util::extractArchive(type, this->newCheatsVer); })); } else { fs::createTree(BOOTLOADER_PL_PATH); @@ -143,8 +143,8 @@ void ListDownloadTab::setDescription(contentType type) "menus/main/bootloaders_text"_i18n); break; case contentType::cheats: - this->newCheatsVer = util::downloadFileToString(CHEATS_URL_VERSION); - this->currentCheatsVer = util::readVersion(CHEATS_VERSION); + this->newCheatsVer = util::getCheatsVersion(); + this->currentCheatsVer = util::readFile(CHEATS_VERSION); description->setText("menus/main/cheats_text"_i18n + this->currentCheatsVer); break; case contentType::payloads: diff --git a/source/tools_tab.cpp b/source/tools_tab.cpp index 617ab05..731c8ba 100644 --- a/source/tools_tab.cpp +++ b/source/tools_tab.cpp @@ -37,7 +37,7 @@ ToolsTab::ToolsTab(const std::string& tag, const nlohmann::ordered_json& payload stagedFrame->addStage( new WorkerPage(stagedFrame, "menus/common/downloading"_i18n, []() { util::downloadArchive(APP_URL, contentType::app); })); stagedFrame->addStage( - new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, [tag]() { util::extractArchive(contentType::app, tag); })); + new WorkerPage(stagedFrame, "menus/common/extracting"_i18n, [tag]() { util::extractArchive(contentType::app); })); stagedFrame->addStage( new ConfirmPage(stagedFrame, "menus/common/all_done"_i18n, true)); brls::Application::pushView(stagedFrame); @@ -48,7 +48,7 @@ ToolsTab::ToolsTab(const std::string& tag, const nlohmann::ordered_json& payload cheats = new brls::ListItem("menus/tools/cheats"_i18n); cheats->getClickEvent()->subscribe([](brls::View* view) { - brls::Application::pushView(new CheatsPage()); + brls::PopupFrame::open("menus/cheats/menu"_i18n, new CheatsPage(), "", ""); }); cheats->setHeight(LISTITEM_HEIGHT); @@ -139,6 +139,7 @@ ToolsTab::ToolsTab(const std::string& tag, const nlohmann::ordered_json& payload std::filesystem::remove(CFW_ZIP_PATH); std::filesystem::remove(FW_ZIP_PATH); std::filesystem::remove(CHEATS_ZIP_PATH); + std::filesystem::remove(CHEATS_VERSION); std::filesystem::remove(SIGPATCHES_ZIP_PATH); fs::removeDir(AMS_DIRECTORY_PATH); fs::removeDir(SEPT_DIRECTORY_PATH); diff --git a/source/utils.cpp b/source/utils.cpp index 8c1fb8c..4a3b49f 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -140,7 +140,7 @@ namespace util { } } - void extractArchive(contentType type, const std::string& tag) + void extractArchive(contentType type, const std::string& version) { chdir(ROOT_PATH); crashIfNotArchive(type); @@ -151,7 +151,7 @@ namespace util { case contentType::cheats: { std::vector titles = extract::getInstalledTitlesNs(); titles = extract::excludeTitles(CHEATS_EXCLUDE, titles); - extract::extractCheats(CHEATS_FILENAME, titles, CurrentCfw::running_cfw); + extract::extractCheats(CHEATS_FILENAME, titles, CurrentCfw::running_cfw, version); break; } case contentType::fw: @@ -256,22 +256,30 @@ namespace util { return str; } - void saveVersion(const std::string& version, const std::string& path) + std::string getCheatsVersion() { - std::ofstream newVersion(path); - newVersion << version << std::endl; + std::string res = util::downloadFileToString(CHEATS_URL_VERSION); + if (res == "" && isArchive(CHEATS_ZIP_PATH)) { + res = "offline"; + } + return res; } - std::string readVersion(const std::string& path) + void saveToFile(const std::string& text, const std::string& path) { - std::fstream versionFile; - std::string version = "0"; - if (std::filesystem::exists(path)) { - versionFile.open(path, std::fstream::in); - versionFile >> version; - versionFile.close(); + std::ofstream file(path); + file << text << std::endl; + } + + std::string readFile(const std::string& path) + { + + std::string text = ""; + std::ifstream file(path); + if (file.good()) { + file >> text; } - return version; + return text; } bool isErista()