diff --git a/Makefile b/Makefile index 79eafde..acd4811 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.5.3 +APP_VERSION := 2.6.0 TARGET := $(notdir $(CURDIR)) ROMFS := resources diff --git a/include/app_page.hpp b/include/app_page.hpp index 3eafc6a..339b702 100644 --- a/include/app_page.hpp +++ b/include/app_page.hpp @@ -6,6 +6,11 @@ typedef struct app App; +enum class appPageType{ + base, + cheatSlips, + gbatempCheats +}; class AppPage : public brls::AppletFrame { @@ -18,5 +23,5 @@ class AppPage : public brls::AppletFrame std::set titles; public: - AppPage(const bool cheatSlips = false); + AppPage(const appPageType type = appPageType::base); }; \ No newline at end of file diff --git a/include/constants.hpp b/include/constants.hpp index ada1fcc..70e93d2 100644 --- a/include/constants.hpp +++ b/include/constants.hpp @@ -41,6 +41,7 @@ constexpr const char CHEATS_URL_VERSION[] = "https://github.com/HamletDuFromage/ constexpr const char LOOKUP_TABLE_URL[] = "https://raw.githubusercontent.com/HamletDuFromage/switch-cheats-db/master/versions.json"; constexpr const char LOOKUP_TABLE_CBOR[] = "https://github.com/HamletDuFromage/switch-cheats-db/raw/master/versions.cbor"; constexpr const char VERSIONS_DIRECTORY[] = "https://raw.githubusercontent.com/HamletDuFromage/switch-cheats-db/master/versions/"; +constexpr const char CHEATS_DIRECTORY[] = "https://raw.githubusercontent.com/HamletDuFromage/switch-cheats-db/master/cheats/"; constexpr const char CHEATSLIPS_CHEATS_URL[] ="https://www.cheatslips.com/api/v1/cheats/"; constexpr const char CHEATSLIPS_TOKEN_URL[] ="https://www.cheatslips.com/api/v1/token"; constexpr const char TOKEN_PATH[] = "/config/aio-switch-updater/token.json"; diff --git a/include/download_cheats_page.hpp b/include/download_cheats_page.hpp index a17b7bf..4b11961 100644 --- a/include/download_cheats_page.hpp +++ b/include/download_cheats_page.hpp @@ -6,21 +6,21 @@ class DownloadCheatsPage : public brls::AppletFrame { - private: + protected: brls::List* list; brls::Label* label; brls::ListItem* del; - brls::ToggleListItem* listItem; - std::vector> toggles; + uint64_t tid = 0; + std::string bid = ""; + u32 version = 0; - public: DownloadCheatsPage(uint64_t tid); - std::string GetBuilID(uint64_t tid); - std::string GetBuilIDFromFile(uint64_t tid); - std::string GetCheatsTitle(nlohmann::json cheat); - void WriteCheats(uint64_t tid, std::string bid, std::string cheatContent); - void DeleteCheats(uint64_t tid, std::string bid); - void ShowCheatsContent(nlohmann::ordered_json titles); + void GetBuildID(); + void GetBuildIDFromDmnt(); + void GetVersion(); + void GetBuildIDFromFile(); + void WriteCheats(std::string cheatContent); + void DeleteCheats(); typedef struct { u64 base; @@ -36,4 +36,24 @@ class DownloadCheatsPage : public brls::AppletFrame DmntMemoryRegionExtents address_space_extents; u8 main_nso_build_id[0x20]; } DmntCheatProcessMetadata; +}; + +class DownloadCheatsPage_CheatSlips : public DownloadCheatsPage { + + private: + brls::ToggleListItem* listItem; + std::vector> toggles; + std::string GetCheatsTitle(nlohmann::json cheat); + void ShowCheatsContent(nlohmann::ordered_json titles); + + public: + DownloadCheatsPage_CheatSlips(uint64_t tid); +}; + +class DownloadCheatsPage_GbaTemp : public DownloadCheatsPage { + private: + brls::ListItem* listItem; + + public: + DownloadCheatsPage_GbaTemp(uint64_t tid); }; \ No newline at end of file diff --git a/include/list_download_tab.hpp b/include/list_download_tab.hpp index b3f3b07..df3f092 100644 --- a/include/list_download_tab.hpp +++ b/include/list_download_tab.hpp @@ -8,10 +8,14 @@ class ListDownloadTab : public brls::List private: brls::ListItem* listItem; brls::ListItem *cheatslipsItem; + brls::ListItem *gbatempItem; brls::Label *notFound; brls::Label *description; - brls::Label *cheatSlipLabel; + brls::Label *cheatsLabel; int size; + void createCheatSlipItem(); + void creategbatempItem(); + public: ListDownloadTab(const archiveType type); brls::View* getDefaultFocus() override; diff --git a/resources/i18n/en-US/menus.json b/resources/i18n/en-US/menus.json index 04da02c..e248a19 100644 --- a/resources/i18n/en-US/menus.json +++ b/resources/i18n/en-US/menus.json @@ -18,8 +18,10 @@ "delete_all": "Delete all cheats", "deleting": "Deleting...", "cheastlips_title": "Cheatslips cheats", + "gbatemp_title": "GBAtemp cheats", + "get_gbatemp": "Download GBAtemp.net cheat codes", "get_cheatslips": "Download CheatSlips.com cheat sheets", - "cheatslips_label": "\ue016 Log into CheatSlips.com and download cheat sheets for your games.", + "cheats_label": "\ue016 Download individual cheat codes from the GBAtemp.net database or cheat sheets from CheatSlips.com", "cheatslips_dl": "Download a selection of cheat sheets from CheatSlips.com.\nThose cheat codes will be added to the end of your existing cheat file.", "delete_file": "Delete existing cheat file", "cheatslips_error": "Could not fetch selected cheat codes/invalid token.", @@ -34,7 +36,10 @@ "exclude_titles": "Exclude titles", "exclude_titles_desc": "You can turn off cheat updates with this menu", "exclude_titles_save": "Save choice and return", - "dl_all": "Download and extract the entire gbatemp cheats archive" + "dl_all": "Download and extract the entire gbatemp cheats archive", + "gbatemp_dl": "Download cheat codes curated from GBAtemp. Those cheats will be added to the end of your existing cheat file.\n\uE016 Build ID: {}", + "gbatemp_dl_cheatcode": "Download cheat code", + "gbatemp_dl_successful_dl": "Successfully downloaded the following cheat code:\n{}" }, "common": { "downloading": "Downloading...", diff --git a/source/app_page.cpp b/source/app_page.cpp index c805f4a..45614c0 100644 --- a/source/app_page.cpp +++ b/source/app_page.cpp @@ -11,15 +11,23 @@ namespace i18n = brls::i18n; using namespace i18n::literals; -AppPage::AppPage(const bool cheatSlips) : AppletFrame(true, true) +AppPage::AppPage(const appPageType type) : AppletFrame(true, true) { - this->setTitle(cheatSlips ? "menus/cheats/cheastlips_title"_i18n : "menus/cheats/installed"_i18n); list = new brls::List(); - label = new brls::Label( - brls::LabelStyle::DESCRIPTION, - cheatSlips ? "menus/cheats/cheatslips_select"_i18n : "menus/cheats/label"_i18n, - true - ); + switch(type){ + case appPageType::base: + this->setTitle("menus/cheats/installed"_i18n); + label = new brls::Label(brls::LabelStyle::DESCRIPTION, "menus/cheats/label"_i18n, true); + break; + case appPageType::cheatSlips: + this->setTitle("menus/cheats/cheastlips_title"_i18n); + label = new brls::Label(brls::LabelStyle::DESCRIPTION, "menus/cheats/cheatslips_select"_i18n, true); + break; + case appPageType::gbatempCheats: + this->setTitle("menus/cheats/gbatemp_title"_i18n); + label = new brls::Label( brls::LabelStyle::DESCRIPTION,"menus/cheats/cheatslips_select"_i18n,true); + break; + } list->addView(label); NsApplicationRecord record; @@ -34,7 +42,7 @@ AppPage::AppPage(const bool cheatSlips) : AppletFrame(true, true) titles = fs::readLineByLine(UPDATED_TITLES_PATH); - if(!titles.empty() || cheatSlips) { + if(!titles.empty() || type == appPageType::cheatSlips || type == appPageType::gbatempCheats) { while (true) { rc = nsListApplicationRecord(&record, sizeof(record), i, &recordCount); @@ -51,17 +59,23 @@ AppPage::AppPage(const bool cheatSlips) : AppletFrame(true, true) i++; continue; } - if(!cheatSlips && titles.find(util::formatApplicationId(tid)) == titles.end()) { + if(type == appPageType::base && titles.find(util::formatApplicationId(tid)) == titles.end()) { i++; continue; } listItem = new brls::ListItem(std::string(langEntry->name), "", util::formatApplicationId(tid)); listItem->setThumbnail(controlData.icon, sizeof(controlData.icon)); - if(cheatSlips){ - listItem->getClickEvent()->subscribe([&, tid](brls::View* view) { - brls::Application::pushView(new DownloadCheatsPage(tid)); - }); + + switch(type){ + case appPageType::cheatSlips: + listItem->getClickEvent()->subscribe([&, tid](brls::View* view) { brls::Application::pushView(new DownloadCheatsPage_CheatSlips(tid)); }); + break; + case appPageType::gbatempCheats: + listItem->getClickEvent()->subscribe([&, tid](brls::View* view) { brls::Application::pushView(new DownloadCheatsPage_GbaTemp(tid)); }); + break; + case appPageType::base: + break; } list->addView(listItem); diff --git a/source/changelog_page.cpp b/source/changelog_page.cpp index c98ff93..4fd84a5 100644 --- a/source/changelog_page.cpp +++ b/source/changelog_page.cpp @@ -32,13 +32,13 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 Now displays the latest installed cheat version.\n\uE016 Now warns in the app title if a new update is available."); verTitles.push_back("v1.2.3"); - changes.push_back("\uE016 Now multilingual (thanks to 'github.com/tiansongyu').\n\uE016 Chinese and French are currently supported."); + changes.push_back("\uE016 Now multilingual (credits to github.com/tiansongyu).\n\uE016 Chinese and French are currently supported."); verTitles.push_back("v1.2.1"); changes.push_back("\uE016 Added option to set a payload to /bootloader/update.bin"); verTitles.push_back("v1.2.2"); - changes.push_back("\uE016 Added japanese localisation (thanks to github.com/yyoossk)."); + changes.push_back("\uE016 Added japanese localisation (credits to github.com/yyoossk)."); verTitles.push_back("v1.2.4"); changes.push_back("\uE016 Fixed app self-update"); @@ -47,7 +47,7 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 Improved japanese translation"); verTitles.push_back("v1.2.6"); - changes.push_back("\uE016 Added spanish translation (thanks to 'https://github.com/sergiou87'"); + changes.push_back("\uE016 Added spanish translation (credits to github.com/sergiou87"); verTitles.push_back("v1.3.0"); changes.push_back("\uE016 Added back the ability to update CFWs"); @@ -77,7 +77,7 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 A few graphical tweaks."); verTitles.push_back("v1.5.2"); - changes.push_back("\uE016 Added support for Traditional Chinese (thanks to 'https://github.com/qazrfv1234')"); + changes.push_back("\uE016 Added support for Traditional Chinese (credits to github.com/qazrfv1234)"); verTitles.push_back("v2.0.0"); changes.push_back("\uE016 Added ability to download cheatslips cheats.\n\uE016 Added way to toggle out tabs.\n\uE016 Various code improvements."); @@ -116,7 +116,7 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 Minor fixes, refactored old switch-cheats updater code and changed way to detect CFW"); verTitles.push_back("v2.4.0"); - changes.push_back("\uE016 Added option to extract the entire gbatemp cheats archive.\n\uE016 Shortened load times.\n\uE016 Added German localisation (thanks to github.com/Slluxx).\n\uE016 Added option to disable sysmodules prior to updating.\n\uE016 Improved Japanese localisation (thanks to github.com/yyoossk).\n\uE016 Added current AMS version display."); + changes.push_back("\uE016 Added option to extract the entire gbatemp cheats archive.\n\uE016 Shortened load times.\n\uE016 Added German localisation (credits to github.com/Slluxx).\n\uE016 Added option to disable sysmodules prior to updating.\n\uE016 Improved Japanese localisation (credits to github.com/yyoossk).\n\uE016 Added current AMS version display."); verTitles.push_back("v2.4.1"); changes.push_back("\uE016 Added information about download progress."); @@ -125,10 +125,10 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 Added option to manually change language.\n\uE016 Fixed broken strings.\n\uE016 Few visual tweaks."); verTitles.push_back("v2.4.3"); - changes.push_back("\uE016 Added way to select system default in language selection.\n\uE016 Display local IP in internet settings.\n\uE016 Added Polish localisation (thanks to https://github.com/teddy74eva).\n\uE016 Updated Traditional Chinese localisation (thanks to https://github.com/qazrfv1234).\n\uE016 Minor code changes."); + changes.push_back("\uE016 Added way to select system default in language selection.\n\uE016 Display local IP in internet settings.\n\uE016 Added Polish localisation (credits to github.com/teddy74eva).\n\uE016 Updated Traditional Chinese localisation (credits to https://github.com/qazrfv1234).\n\uE016 Minor code changes."); verTitles.push_back("v2.4.4"); - changes.push_back("\uE016 Significantly reduced time to retrieve build IDs.\n\uE016 Updated Polish localisation (thanks to https://github.com/teddy74eva)."); + changes.push_back("\uE016 Significantly reduced time to retrieve build IDs.\n\uE016 Updated Polish localisation (credits to github.com/teddy74eva)."); verTitles.push_back("v2.4.5-fix_ams"); changes.push_back("\uE016 Atmosphère 0.19+ support. Note that this version assumes your switch is running Atmosphère. I should fix this soon, but if you're on SXOS, please stay on 2.4.4."); @@ -152,11 +152,14 @@ ChangelogPage::ChangelogPage() : AppletFrame(true, true) changes.push_back("\uE016 Fixed bug copying Mariko payloads on Erista."); verTitles.push_back("v2.5.2"); - changes.push_back("\uE016 Updated Japanese and Traditional Chinese translations (thanks to yyoossk and qazrfv1234).\n\uE016 Updated payload so that it doesn't throw errors if the bootloader folder is missing.\n\uE016 Minor code changes that may or may not result in performace improvements."); + changes.push_back("\uE016 Updated Japanese and Traditional Chinese translations (credits to github.com/yyoossk and github.com/qazrfv1234).\n\uE016 Updated payload so that it doesn't throw errors if the bootloader folder is missing.\n\uE016 Minor code changes that may or may not result in performace improvements."); verTitles.push_back("v2.5.3"); changes.push_back("\uE016 Check available size before downloading and extracting files.\n\uE016 Now displaying a message when the custom payload is running."); + verTitles.push_back("v2.6.0"); + changes.push_back("\uE016 Added ability to download invidual cheet codes from the GBAtemp.net archive.\n\uE016 Updated Polish translation (credits to github.com/teddy74eva)"); + for(int i = verTitles.size() -1 ; i >= 0; i--){ listItem = new brls::ListItem(verTitles[i]); change = changes[i]; diff --git a/source/download.cpp b/source/download.cpp index 050433f..f1d82a1 100644 --- a/source/download.cpp +++ b/source/download.cpp @@ -294,8 +294,7 @@ std::vector downloadPageBinary(const std::string& url, std::vector } nlohmann::ordered_json getRequest(const std::string& url, std::vector headers, std::string body) { - std::string request; - request = downloadPage(url, headers, body); + std::string request = downloadPage(url, headers, body); if(json::accept(request)) return nlohmann::ordered_json::parse(request); else return nlohmann::ordered_json::object(); diff --git a/source/download_cheats_page.cpp b/source/download_cheats_page.cpp index 2314142..cb650b7 100644 --- a/source/download_cheats_page.cpp +++ b/source/download_cheats_page.cpp @@ -11,27 +11,117 @@ namespace i18n = brls::i18n; using namespace i18n::literals; using json = nlohmann::json; -DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) +DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true), tid(tid) +{ + GetVersion(); + GetBuildID(); + this->setTitle("menus/cheats/menu"_i18n); + this->setFooterText("Game version: v" + std::to_string(this->version / 0x10000)); +} + +void DownloadCheatsPage::GetBuildID() { + if(CurrentCfw::running_cfw == CFW::ams) + GetBuildIDFromDmnt(); + if(this->bid == "") + GetBuildIDFromFile(); +} + +void DownloadCheatsPage::GetBuildIDFromDmnt() { + static Service g_dmntchtSrv; + DmntCheatProcessMetadata metadata; + smGetService(&g_dmntchtSrv, "dmnt:cht"); + serviceDispatch(&g_dmntchtSrv, 65003); + serviceDispatchOut(&g_dmntchtSrv, 65002, metadata); + serviceClose(&g_dmntchtSrv); + if(metadata.title_id == this->tid){ + u8 buildID[0x20]; + memcpy(buildID, metadata.main_nso_build_id, 0x20); + std::stringstream ss; + for (u8 i = 0; i < 8; i++) + ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; + this->bid = ss.str(); + } + else{ + this->bid = ""; + } +} + +void DownloadCheatsPage::GetVersion() { + NsApplicationContentMetaStatus *MetaSatus = new NsApplicationContentMetaStatus[100U]; + s32 out; + nsListApplicationContentMetaStatus(this->tid, 0, MetaSatus, 100, &out); + for(int i = 0; i < out ; i++) { + if(version < MetaSatus[i].version) this->version = MetaSatus[i].version; + } +} + +void DownloadCheatsPage::GetBuildIDFromFile() { + json versions_json = download::getRequest(VERSIONS_DIRECTORY + util::formatApplicationId(this->tid) + ".json"); + + std::string version_str = std::to_string(this->version); + if(versions_json.find(version_str) != versions_json.end()) { + this->bid = versions_json[version_str]; + } + else { + this->bid = ""; + } +} + +void DownloadCheatsPage::WriteCheats(std::string cheatContent) { + std::string path; + std::string tidstr = util::formatApplicationId(this->tid); + switch(CurrentCfw::running_cfw){ + case CFW::ams: + path = std::string(AMS_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::rnx: + path = std::string(REINX_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::sxos: + path = std::string(SXOS_PATH) + std::string(TITLES_PATH); + break; + } + path += tidstr + "/cheats/"; + fs::createTree(path); + path += this->bid + ".txt"; + std::ofstream cheatFile; + cheatFile.open(path, std::ios::app); + cheatFile << "\n\n" << cheatContent; + std::ofstream updated; + updated.open(UPDATED_TITLES_PATH, std::ios::app); + updated << "\n" << tidstr; +} + +void DownloadCheatsPage::DeleteCheats() { + std::string path; + switch(CurrentCfw::running_cfw){ + case CFW::ams: + path = std::string(AMS_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::rnx: + path = std::string(REINX_PATH) + std::string(CONTENTS_PATH); + break; + case CFW::sxos: + path = std::string(SXOS_PATH) + std::string(TITLES_PATH); + break; + } + std::filesystem::remove(path + util::formatApplicationId(this->tid) + "/cheats/" + this->bid + ".txt"); +} + +DownloadCheatsPage_CheatSlips::DownloadCheatsPage_CheatSlips(uint64_t tid) : DownloadCheatsPage(tid) { this->setTitle("menus/cheats/menu"_i18n); - - std::string bid = ""; - if(CurrentCfw::running_cfw == CFW::ams) - bid = GetBuilID(tid); - if(bid == "") - bid = GetBuilIDFromFile(tid); - list = new brls::List(); label = new brls::Label( brls::LabelStyle::DESCRIPTION, - "menus/cheats/cheatslips_dl"_i18n + "\n\uE016 Build ID: " + bid, + "menus/cheats/cheatslips_dl"_i18n + "\n\uE016 Build ID: " + this->bid, true ); list->addView(label); - if(bid != "") { + if(this->bid != "") { std::vector headers = {"accept: application/json"}; - json cheatsInfo = download::getRequest(CHEATSLIPS_CHEATS_URL + util::formatApplicationId(tid) + "/" + bid, headers); + json cheatsInfo = download::getRequest(CHEATSLIPS_CHEATS_URL + util::formatApplicationId(this->tid) + "/" + this->bid, headers); if(cheatsInfo.find("cheats") != cheatsInfo.end()) { for (const auto& p : cheatsInfo["cheats"].items()) { json cheat = p.value(); @@ -58,7 +148,7 @@ DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) list->addView(label); } - list->registerAction((bid != "") ? "menus/cheats/cheatslips_dl_cheats"_i18n : "brls/hints/back"_i18n, brls::Key::B, [this, bid, tid] { + list->registerAction((this->bid != "") ? "menus/cheats/cheatslips_dl_cheats"_i18n : "brls/hints/back"_i18n, brls::Key::B, [this] { std::vector ids; for(auto& e : toggles){ if(e.first->getToggleState()){ @@ -75,7 +165,7 @@ DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) if(token.find("token") != token.end()) { headers.push_back("X-API-TOKEN: " + token["token"].get()); } - json cheatsInfo = download::getRequest("https://www.cheatslips.com/api/v1/cheats/" + util::formatApplicationId(tid) + "/" + bid, headers); + nlohmann::ordered_json cheatsInfo = download::getRequest("https://www.cheatslips.com/api/v1/cheats/" + util::formatApplicationId(this->tid) + "/" + this->bid, headers); if(cheatsInfo.find("cheats") != cheatsInfo.end()) { for (const auto& p : cheatsInfo["cheats"].items()) { if(std::find(ids.begin(), ids.end(), p.value()["id"]) != ids.end()) { @@ -83,7 +173,7 @@ DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) error = 1; } else { - WriteCheats(tid, bid, p.value()["content"]); + WriteCheats(p.value()["content"]); } } } @@ -132,8 +222,8 @@ DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) }); del = new brls::ListItem("menus/cheats/delete_file"_i18n); - del->getClickEvent()->subscribe([this, tid, bid](brls::View* view) { - DeleteCheats(tid, bid); + del->getClickEvent()->subscribe([this](brls::View* view) { + DeleteCheats(); brls::Dialog* dialog = new brls::Dialog("menus/common/all_done"_i18n); brls::GenericEvent::Callback callback = [dialog](brls::View* view) { dialog->close(); @@ -145,50 +235,8 @@ DownloadCheatsPage::DownloadCheatsPage(uint64_t tid) : AppletFrame(true, true) list->addView(del); this->setContentView(list); } -std::string DownloadCheatsPage::GetBuilID(uint64_t tid) { - static Service g_dmntchtSrv; - DmntCheatProcessMetadata metadata; - smGetService(&g_dmntchtSrv, "dmnt:cht"); - serviceDispatch(&g_dmntchtSrv, 65003); - serviceDispatchOut(&g_dmntchtSrv, 65002, metadata); - serviceClose(&g_dmntchtSrv); - if(metadata.title_id == tid){ - u8 buildID[0x20]; - memcpy(buildID, metadata.main_nso_build_id, 0x20); - std::stringstream ss; - for (u8 i = 0; i < 8; i++) - ss << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << (u16)buildID[i]; - return ss.str(); - } - else{ - return ""; - } -} -std::string DownloadCheatsPage::GetBuilIDFromFile(uint64_t tid) { - NsApplicationContentMetaStatus *MetaSatus = new NsApplicationContentMetaStatus[100U]; - s32 out; - nsListApplicationContentMetaStatus(tid, 0, MetaSatus, 100, &out); - u32 v = 0; - for(int i = 0; i < out ; i++) { - if(v < MetaSatus[i].version) v = MetaSatus[i].version; - } - - this->setFooterText("Game version: v" + std::to_string(v / 0x10000)); - std::string version = std::to_string(v); - - std::string versions_str = download::downloadPage(VERSIONS_DIRECTORY + util::formatApplicationId(tid) + ".json"); - json versions; - if (json::accept(versions_str)) versions = json::parse(versions_str); - else versions = json::object(); - - if(versions.find(version) != versions.end()) { - return versions[version]; - } - return ""; -} - -std::string DownloadCheatsPage::GetCheatsTitle(json cheat) { +std::string DownloadCheatsPage_CheatSlips::GetCheatsTitle(json cheat) { std::string res = ""; if(cheat.find("titles") != cheat.end()) { for(auto& p : cheat["titles"]){ @@ -202,48 +250,7 @@ std::string DownloadCheatsPage::GetCheatsTitle(json cheat) { return res; } -void DownloadCheatsPage::WriteCheats(uint64_t tid, std::string bid, std::string cheatContent) { - std::string path; - std::string tidstr = util::formatApplicationId(tid); - switch(CurrentCfw::running_cfw){ - case CFW::ams: - path = std::string(AMS_PATH) + std::string(CONTENTS_PATH); - break; - case CFW::rnx: - path = std::string(REINX_PATH) + std::string(CONTENTS_PATH); - break; - case CFW::sxos: - path = std::string(SXOS_PATH) + std::string(TITLES_PATH); - break; - } - path += tidstr + "/cheats/"; - fs::createTree(path); - path += bid + ".txt"; - std::ofstream cheatFile; - cheatFile.open(path, std::ios::app); - cheatFile << "\n\n" << cheatContent; - std::ofstream updated; - updated.open(UPDATED_TITLES_PATH, std::ios::app); - updated << "\n" << tidstr; -} - -void DownloadCheatsPage::DeleteCheats(uint64_t tid, std::string bid) { - std::string path; - switch(CurrentCfw::running_cfw){ - case CFW::ams: - path = std::string(AMS_PATH) + std::string(CONTENTS_PATH); - break; - case CFW::rnx: - path = std::string(REINX_PATH) + std::string(CONTENTS_PATH); - break; - case CFW::sxos: - path = std::string(SXOS_PATH) + std::string(TITLES_PATH); - break; - } - std::filesystem::remove(path + util::formatApplicationId(tid) + "/cheats/" + bid + ".txt"); -} - -void DownloadCheatsPage::ShowCheatsContent(nlohmann::ordered_json titles) { +void DownloadCheatsPage_CheatSlips::ShowCheatsContent(nlohmann::ordered_json titles) { brls::AppletFrame* appView = new brls::AppletFrame(true, true); brls::List* list = new brls::List(); brls::ListItem* listItem; @@ -256,4 +263,63 @@ void DownloadCheatsPage::ShowCheatsContent(nlohmann::ordered_json titles) { } appView->setContentView(list); brls::PopupFrame::open("menus/cheats/sheet_content"_i18n, appView, "", ""); -} \ No newline at end of file +} + +DownloadCheatsPage_GbaTemp::DownloadCheatsPage_GbaTemp(uint64_t tid) : DownloadCheatsPage(tid) +{ + list = new brls::List(); + label = new brls::Label( + brls::LabelStyle::DESCRIPTION, + fmt::format("menus/cheats/gbatemp_dl"_i18n, this->bid), + true + ); + list->addView(label); + + if(this->bid != "") { + nlohmann::ordered_json cheatsJson = download::getRequest(CHEATS_DIRECTORY + util::formatApplicationId(this->tid) + ".json"); + if(cheatsJson.find(this->bid) != cheatsJson.end()) { + for (const auto& p : cheatsJson[this->bid].items()) { + json cheat = p.value(); + listItem = new::brls::ListItem(cheat["title"]); + listItem->registerAction("menus/cheats/gbatemp_dl_cheatcode"_i18n, brls::Key::A, [this, cheat] { + WriteCheats(cheat["content"]); + brls::Dialog* dialog = new brls::Dialog(fmt::format("menus/cheats/gbatemp_dl_successful_dl"_i18n, cheat["title"])); + brls::GenericEvent::Callback callback = [dialog](brls::View* view) { + dialog->close(); + }; + dialog->addButton("menus/common/ok"_i18n, callback); + dialog->setCancelable(true); + dialog->open(); + return true; + }); + list->addView(listItem); + } + list->addView(new brls::ListItemGroupSpacing(true)); + } + + } + + else { + label = new brls::Label( + brls::LabelStyle::REGULAR, + "menus/cheats/bid_not_found"_i18n, + true + ); + list->addView(label); + } + + del = new brls::ListItem("menus/cheats/delete_file"_i18n); + del->getClickEvent()->subscribe([this](brls::View* view) { + DeleteCheats(); + brls::Dialog* dialog = new brls::Dialog("menus/common/all_done"_i18n); + brls::GenericEvent::Callback callback = [dialog](brls::View* view) { + dialog->close(); + }; + dialog->addButton("menus/common/ok"_i18n, callback); + dialog->setCancelable(true); + dialog->open(); + }); + list->addView(del); + this->setContentView(list); +} + diff --git a/source/list_download_tab.cpp b/source/list_download_tab.cpp index 0d384fd..65260cc 100644 --- a/source/list_download_tab.cpp +++ b/source/list_download_tab.cpp @@ -121,68 +121,85 @@ ListDownloadTab::ListDownloadTab(const archiveType type) : } if(type == archiveType::cheats){ - cheatSlipLabel = new brls::Label( - brls::LabelStyle::DESCRIPTION, - "menus/cheats/cheatslips_label"_i18n, - true + cheatsLabel = new brls::Label( + brls::LabelStyle::DESCRIPTION, + "menus/cheats/cheats_label"_i18n, + true ); - this->addView(cheatSlipLabel); - this->size += 1; - cheatslipsItem = new brls::ListItem("menus/cheats/get_cheatslips"_i18n); - cheatslipsItem->setHeight(LISTITEM_HEIGHT); - cheatslipsItem->getClickEvent()->subscribe([&](brls::View* view) { - if(std::filesystem::exists(TOKEN_PATH)) { - brls::Application::pushView(new AppPage(true)); + this->addView(cheatsLabel); + creategbatempItem(); + createCheatSlipItem(); + } +} + +void ListDownloadTab::createCheatSlipItem() { + this->size += 1; + cheatslipsItem = new brls::ListItem("menus/cheats/get_cheatslips"_i18n); + cheatslipsItem->setHeight(LISTITEM_HEIGHT); + cheatslipsItem->getClickEvent()->subscribe([&](brls::View* view) { + if(std::filesystem::exists(TOKEN_PATH)) { + brls::Application::pushView(new AppPage(appPageType::cheatSlips)); + return true; + } + else { + SwkbdConfig kbd; + char usr[0x100] = {0}; + char pwd[0x100] = {0}; + Result rc = swkbdCreate(&kbd, 0); + if (R_SUCCEEDED(rc)) { + swkbdConfigMakePresetDefault(&kbd); + swkbdConfigSetOkButtonText(&kbd, "Submit"); + swkbdConfigSetGuideText(&kbd, "www.cheatslips.com e-mail"); + swkbdShow(&kbd, usr, sizeof(usr)); + swkbdClose(&kbd); + rc = swkbdCreate(&kbd, 0); + if(R_SUCCEEDED(rc)){ + swkbdConfigMakePresetPassword(&kbd); + swkbdConfigSetOkButtonText(&kbd, "Submit"); + swkbdConfigSetGuideText(&kbd, "www.cheatslips.com password"); + swkbdShow(&kbd, pwd, sizeof(pwd)); + swkbdClose(&kbd); + } + } + std::string body = "{\"email\":\"" + std::string(usr) + + "\",\"password\":\"" + std::string(pwd) + "\"}"; + nlohmann::json token = download::getRequest(CHEATSLIPS_TOKEN_URL, + {"Accept: application/json", + "Content-Type: application/json", + "charset: utf-8"}, + body); + if(token.find("token") != token.end()) { + std::ofstream tokenFile(TOKEN_PATH); + tokenFile << token.dump(); + tokenFile.close(); + brls::Application::pushView(new AppPage(appPageType::cheatSlips)); return true; } else { - SwkbdConfig kbd; - char usr[0x100] = {0}; - char pwd[0x100] = {0}; - Result rc = swkbdCreate(&kbd, 0); - if (R_SUCCEEDED(rc)) { - swkbdConfigMakePresetDefault(&kbd); - swkbdConfigSetOkButtonText(&kbd, "Submit"); - swkbdConfigSetGuideText(&kbd, "www.cheatslips.com e-mail"); - swkbdShow(&kbd, usr, sizeof(usr)); - swkbdClose(&kbd); - rc = swkbdCreate(&kbd, 0); - if(R_SUCCEEDED(rc)){ - swkbdConfigMakePresetPassword(&kbd); - swkbdConfigSetOkButtonText(&kbd, "Submit"); - swkbdConfigSetGuideText(&kbd, "www.cheatslips.com password"); - swkbdShow(&kbd, pwd, sizeof(pwd)); - swkbdClose(&kbd); - } - } - std::string body = "{\"email\":\"" + std::string(usr) - + "\",\"password\":\"" + std::string(pwd) + "\"}"; - nlohmann::json token = download::getRequest(CHEATSLIPS_TOKEN_URL, - {"Accept: application/json", - "Content-Type: application/json", - "charset: utf-8"}, - body); - if(token.find("token") != token.end()) { - std::ofstream tokenFile(TOKEN_PATH); - tokenFile << token.dump(); - tokenFile.close(); - brls::Application::pushView(new AppPage(true)); - return true; - } - else { - brls::Dialog* dialog = new brls::Dialog("menus/cheats/cheatslips_wrong_id"_i18n + "\n" + "menus/cheats/kb_error"_i18n); - brls::GenericEvent::Callback callback = [dialog](brls::View* view) { - dialog->close(); - }; - dialog->addButton("menus/common/ok"_i18n, callback); - dialog->setCancelable(true); - dialog->open(); - return true; - } + brls::Dialog* dialog = new brls::Dialog("menus/cheats/cheatslips_wrong_id"_i18n + "\n" + "menus/cheats/kb_error"_i18n); + brls::GenericEvent::Callback callback = [dialog](brls::View* view) { + dialog->close(); + }; + dialog->addButton("menus/common/ok"_i18n, callback); + dialog->setCancelable(true); + dialog->open(); + return true; } - }); - this->addView(cheatslipsItem); - } + } + }); + this->addView(cheatslipsItem); +} + + +void ListDownloadTab::creategbatempItem() { + this->size += 1; + gbatempItem = new brls::ListItem("menus/cheats/get_gbatemp"_i18n); + gbatempItem->setHeight(LISTITEM_HEIGHT); + gbatempItem->getClickEvent()->subscribe([&](brls::View* view) { + brls::Application::pushView(new AppPage(appPageType::gbatempCheats)); + return true; + }); + this->addView(gbatempItem); } brls::View* ListDownloadTab::getDefaultFocus() diff --git a/source/utils.cpp b/source/utils.cpp index 5fbf7fe..df20d06 100644 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -1,4 +1,3 @@ -#include #include "utils.hpp" #include "fs.hpp" #include "current_cfw.hpp" @@ -8,9 +7,11 @@ #include "main_frame.hpp" #include "reboot_payload.h" #include "unistd.h" +#include #include #include + namespace i18n = brls::i18n; using namespace i18n::literals;