From 8e761e70093be3340c44601375c9dcc27a602754 Mon Sep 17 00:00:00 2001 From: flb Date: Sat, 25 Sep 2021 02:14:38 +0200 Subject: [PATCH] improve cheats extraction, now suports multicontent games --- Makefile | 2 +- source/extract.cpp | 137 ++++++++++++--------------------------------- 2 files changed, 38 insertions(+), 101 deletions(-) diff --git a/Makefile b/Makefile index bd18ab3..a57ecba 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ CFLAGS += $(INCLUDE) -D__SWITCH__ \ -DAPP_TITLE="\"$(APP_TITLE)\"" -DAPP_TITLE_LOWER="\"$(TARGET)\"" -CXXFLAGS := $(CFLAGS) -std=gnu++17 -fexceptions -Wno-reorder +CXXFLAGS := $(CFLAGS) -std=gnu++20 -fexceptions -Wno-reorder ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) diff --git a/source/extract.cpp b/source/extract.cpp index c0f3094..7aa300f 100644 --- a/source/extract.cpp +++ b/source/extract.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -179,93 +180,51 @@ namespace extract { return diff; } + int computeOffset(CFW cfw) + { + switch (cfw) { + case CFW::ams: + std::filesystem::create_directory(AMS_PATH); + std::filesystem::create_directory(AMS_CONTENTS); + chdir(AMS_PATH); + return std::string(CONTENTS_PATH).length(); + break; + case CFW::rnx: + std::filesystem::create_directory(REINX_PATH); + std::filesystem::create_directory(REINX_CONTENTS); + chdir(REINX_PATH); + return std::string(CONTENTS_PATH).length(); + break; + case CFW::sxos: + std::filesystem::create_directory(SXOS_PATH); + std::filesystem::create_directory(SXOS_TITLES); + chdir(SXOS_PATH); + return std::string(TITLES_PATH).length(); + break; + } + return 0; + } + void extractCheats(const std::string& zipPath, std::vector titles, CFW cfw, bool credits) { zipper::Unzipper unzipper(zipPath); std::vector entries = unzipper.entries(); - //std::set extractedTitles; - int offset = 0; - switch (cfw) { - case CFW::ams: - offset = std::string(CONTENTS_PATH).length(); - std::filesystem::create_directory(AMS_PATH); - std::filesystem::create_directory(AMS_CONTENTS); - chdir(AMS_PATH); - break; - case CFW::rnx: - offset = std::string(CONTENTS_PATH).length(); - std::filesystem::create_directory(REINX_PATH); - std::filesystem::create_directory(REINX_CONTENTS); - chdir(REINX_PATH); - break; - case CFW::sxos: - offset = std::string(TITLES_PATH).length(); - std::filesystem::create_directory(SXOS_PATH); - std::filesystem::create_directory(SXOS_TITLES); - chdir(SXOS_PATH); - break; - } + int offset = computeOffset(cfw); - std::vector entriesNames; - std::vector parentIndexes; - for (size_t i = 1; i < entries.size(); i++) { - entriesNames.push_back(entries[i].name); - } - - std::sort(entriesNames.begin(), entriesNames.end(), caselessCompare); - - std::vector parents; - std::vector> children; - std::vector tempChildren; - - size_t k = 0; - while (k < entriesNames.size()) { - if (entriesNames[k].length() == (size_t)(offset + 17)) { - parents.push_back(entriesNames[k]); - k++; - while (entriesNames[k].length() != (size_t)(offset + 17) && k < entriesNames.size()) { - if (credits == false) { - if (strcasecmp(entriesNames[k].substr(offset + 16, 7).c_str(), "/cheats") == 0) { - tempChildren.push_back(entriesNames[k]); - } - } - else { - tempChildren.push_back(entriesNames[k]); - } - k++; - } - children.push_back(tempChildren); - tempChildren.clear(); - } - else { - k++; - } - } - - size_t lastL = 0; - std::string id; - ProgressEvent::instance().setTotalSteps(titles.size()); - for (size_t j = 0; j < titles.size(); j++) { + ProgressEvent::instance().setTotalSteps(titles.size() + 1); + for (const auto& title : titles) { if (ProgressEvent::instance().getInterupt()) { break; } - for (size_t l = lastL; l < parents.size(); l++) { - if (strcasecmp((titles[j]).c_str(), parents[l].substr(offset, 16).c_str()) == 0) { - unzipper.extractEntry(parents[l]); - for (auto& e : children[l]) { - unzipper.extractEntry(e); - //extractedTitles.insert(id); - ProgressEvent::instance().setStep(j); - id = e.substr(offset, 16); - std::transform(id.begin(), id.end(), id.begin(), ::toupper); - } - lastL = l; - break; - } + auto matches = entries | std::views::filter([&title, offset](zipper::ZipEntry entry) { + return strcasecmp((title.substr(0, 13)).c_str(), entry.name.substr(offset, 13).c_str()) == 0 && strcasecmp(entry.name.substr(offset + 16, 7).c_str(), "/cheats") == 0; + }); + for (const auto& match : matches) { + unzipper.extractEntry(match.name); + ProgressEvent::instance().incrementStep(1); } } unzipper.close(); - //writeTitlesToFile(extractedTitles, UPDATED_TITLES_PATH); download::downloadFile(CHEATS_URL_VERSION, CHEATS_VERSION, OFF); ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); } @@ -274,41 +233,19 @@ namespace extract { { zipper::Unzipper unzipper(zipPath); std::vector entries = unzipper.entries(); + int offset = computeOffset(cfw); - int offset = 0; - switch (cfw) { - case CFW::ams: - offset = std::string(CONTENTS_PATH).length() + 17 + 7; - std::filesystem::create_directory(AMS_PATH); - std::filesystem::create_directory(AMS_CONTENTS); - chdir(AMS_PATH); - break; - case CFW::rnx: - offset = std::string(CONTENTS_PATH).length() + 17 + 7; - std::filesystem::create_directory(REINX_PATH); - std::filesystem::create_directory(REINX_CONTENTS); - chdir(REINX_PATH); - break; - case CFW::sxos: - offset = std::string(TITLES_PATH).length() + 17 + 7; - std::filesystem::create_directory(SXOS_PATH); - std::filesystem::create_directory(SXOS_TITLES); - chdir(SXOS_PATH); - break; - } - ProgressEvent::instance().setTotalSteps(entries.size()); + 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)))) { - //extractedTitles.insert(util::upperCase(entry.name.substr(offset - 24, 16))); unzipper.extractEntry(entry.name); } ProgressEvent::instance().incrementStep(1); } unzipper.close(); - //writeTitlesToFile(extractedTitles, UPDATED_TITLES_PATH); download::downloadFile(CHEATS_URL_VERSION, CHEATS_VERSION, OFF); ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); }