From 0883c8fe112b91827e8152b423cd296c5ef86430 Mon Sep 17 00:00:00 2001 From: Irne Racoonovich Date: Wed, 15 May 2024 22:51:24 +0300 Subject: [PATCH] Auto format source files using clang-format --- source/FanSliderOverlay.hpp | 88 ++-- source/HelpOverlay.hpp | 38 +- source/IniSection.hpp | 28 +- source/JsonInfoOverlay.hpp | 70 ++-- source/KipInfoOverlay.hpp | 67 ++-- source/debug_funcs.hpp | 12 +- source/download_funcs.hpp | 67 ++-- source/get_funcs.hpp | 122 +++--- source/hex_funcs.hpp | 75 ++-- source/ini_funcs.hpp | 178 +++++---- source/json_funcs.hpp | 37 +- source/main.cpp | 775 ++++++++++++++++++------------------ source/path_funcs.hpp | 103 ++--- source/string_funcs.hpp | 53 ++- source/text_funcs.hpp | 119 +++--- source/utils.hpp | 212 +++++----- 16 files changed, 1099 insertions(+), 945 deletions(-) diff --git a/source/FanSliderOverlay.hpp b/source/FanSliderOverlay.hpp index f65ffd83..478d421a 100644 --- a/source/FanSliderOverlay.hpp +++ b/source/FanSliderOverlay.hpp @@ -1,23 +1,26 @@ -#define NDEBUG -#define STBTT_STATIC -#define TESLA_INIT_IMPL -#include +#pragma once + #include +#include #include class FanSliderOverlay : public tsl::Gui { private: - std::string filePath, specificKey ; + std::string filePath, specificKey; std::vector> commands; std::string helpPath = ""; - public: - FanSliderOverlay(const std::string& file, const std::string& key = "", const std::vector>& cmds = {}) - : filePath(file), specificKey(key), commands(cmds) {} - ~FanSliderOverlay() {} + FanSliderOverlay(const std::string& file, const std::string& key = "", const std::vector>& cmds = {}) + : filePath(file) + , specificKey(key) + , commands(cmds) + { + } + ~FanSliderOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("FanSliderOverlay"); size_t fifthSlashPos = filePath.find('/', filePath.find('/', filePath.find('/', filePath.find('/') + 1) + 1) + 1); @@ -34,11 +37,10 @@ class FanSliderOverlay : public tsl::Gui { helpPath += "/Help/" + getNameWithoutPrefix(getNameFromPath(filePath)) + ".txt"; } if (isFileOrDirectory(helpPath)) { - hasHelp = true; + hasHelp = true; } else { helpPath = ""; } - } auto rootFrame = new tsl::elm::OverlayFrame(specificKey.empty() ? getNameWithoutPrefix(getNameFromPath(filePath)) : specificKey, "Uberhand Package", "", hasHelp, "\uE0E1 Back \uE0E0 Apply "); @@ -47,13 +49,15 @@ class FanSliderOverlay : public tsl::Gui { std::string sourceIni = ""; std::string sectionIni = ""; std::string keyIni = ""; - enum fanModes {Both, Handheld, Console}; + enum fanModes { Both, + Handheld, + Console }; fanModes fanMode = fanModes::Both; - + for (const auto& cmd : commands) { if (cmd.size() > 1) { if (cmd[0] == "slider_ini") { - sourceIni = preprocessPath(cmd[1]); + sourceIni = preprocessPath(cmd[1]); if (cmd[2] == "handheld") { fanMode = fanModes::Handheld; } else if (cmd[2] == "console") { @@ -62,7 +66,7 @@ class FanSliderOverlay : public tsl::Gui { fanMode = fanModes::Both; } } - } + } } if (!isFileOrDirectory(sourceIni)) { @@ -83,8 +87,8 @@ class FanSliderOverlay : public tsl::Gui { std::string iniString = readIniValue(sourceIni, "tc", (fanMode == fanModes::Console or fanMode == fanModes::Both) ? "tskin_rate_table_console_on_fwdbg" : "tskin_rate_table_handheld_on_fwdbg"); std::vector> iniValues = parseIntIniData(iniString); for (const auto& arr : iniValues) { - std::string low = arr[0] < 0 ? "0" : std::to_string(arr[0]/1000) + "°C"; - std::string high = arr[1] > 100000 ? "100°C" : std::to_string((arr[1]/1000) - 1) + "°C"; + std::string low = arr[0] < 0 ? "0" : std::to_string(arr[0] / 1000) + "°C"; + std::string high = arr[1] > 100000 ? "100°C" : std::to_string((arr[1] / 1000) - 1) + "°C"; std::string header = "Max fan speed at " + low + "-" + high + ": "; double stepSize = 0.05 * 255; int percentage = 0; @@ -92,30 +96,29 @@ class FanSliderOverlay : public tsl::Gui { percentage = static_cast(ceil(arr[3] / stepSize)); } - auto slider = new tsl::elm::NamedStepTrackBar(" ",{header + "0%", header + "5%", header + "10%", header + "15%", header + "20%", header + "25%", header + "30%", header + "35%", header + "40%", header + "45%", header + "50%", header + "55%", header + "60%", header + "65%", header + "70%", header + "75%", header + "80%", header + "85%", header + "90%", header + "95%", header+"100%"}); - + auto slider = new tsl::elm::NamedStepTrackBar(" ", { header + "0%", header + "5%", header + "10%", header + "15%", header + "20%", header + "25%", header + "30%", header + "35%", header + "40%", header + "45%", header + "50%", header + "55%", header + "60%", header + "65%", header + "70%", header + "75%", header + "80%", header + "85%", header + "90%", header + "95%", header + "100%" }); + slider->setProgress(percentage); slider->setValueChangedListener([this, list, slider](u8 val) { size_t listSize = list->getSize(); size_t sliderIndex = list->getIndexInList(slider); - if (sliderIndex != 0) { - for (size_t i = 0; i < sliderIndex; i++) { - if (list->getItemAtIndex(i)->getClass() == tsl::Class::TrackBar) { - tsl::elm::NamedStepTrackBar* prevSlider = dynamic_cast(list->getItemAtIndex(i)); - if (prevSlider->getProgress() > val) - { - prevSlider->setProgressVal(val); - } + if (sliderIndex != 0) { + for (size_t i = 0; i < sliderIndex; i++) { + if (list->getItemAtIndex(i)->getClass() == tsl::Class::TrackBar) { + tsl::elm::NamedStepTrackBar* prevSlider = dynamic_cast(list->getItemAtIndex(i)); + if (prevSlider->getProgress() > val) { + prevSlider->setProgressVal(val); } } } - for (size_t i = sliderIndex; i < listSize; i++) { - if (list->getItemAtIndex(i)->getClass() == tsl::Class::TrackBar) { - tsl::elm::NamedStepTrackBar* curSlider = dynamic_cast(list->getItemAtIndex(i)); - if (curSlider->getProgress() < val) - curSlider->setProgressVal(val); - } + } + for (size_t i = sliderIndex; i < listSize; i++) { + if (list->getItemAtIndex(i)->getClass() == tsl::Class::TrackBar) { + tsl::elm::NamedStepTrackBar* curSlider = dynamic_cast(list->getItemAtIndex(i)); + if (curSlider->getProgress() < val) + curSlider->setProgressVal(val); } + } }); slider->setClickListener([this, list, iniString, sourceIni, iniValues, fanMode, stepSize](uint64_t keys) { // Add 'command' to the capture list if (keys & KEY_A) { @@ -123,7 +126,7 @@ class FanSliderOverlay : public tsl::Gui { size_t listSize = list->getSize(); for (size_t i = 0; i < listSize; i++) { if (list->getItemAtIndex(i)->getClass() == tsl::Class::TrackBar) { - values.push_back(int(double(dynamic_cast(list->getItemAtIndex(i))->getProgressStep())*stepSize)); + values.push_back(int(double(dynamic_cast(list->getItemAtIndex(i))->getProgressStep()) * stepSize)); } } if (fanMode == fanModes::Both) { @@ -132,7 +135,7 @@ class FanSliderOverlay : public tsl::Gui { } else { setIniFileValue(sourceIni, "tc", (fanMode == fanModes::Handheld) ? "tskin_rate_table_handheld_on_fwdbg" : "tskin_rate_table_console_on_fwdbg", formString(values, parseIntIniData(iniString, false))); } - + applied = true; tsl::goBack(); return true; @@ -142,10 +145,11 @@ class FanSliderOverlay : public tsl::Gui { list->addItem(slider); } rootFrame->setContent(list); - return rootFrame; + return rootFrame; } - std::string formString(std::vector newValues, const std::vector>& initialData) { + std::string formString(std::vector newValues, const std::vector>& initialData) + { std::stringstream result; result << "\"str!\"[["; @@ -168,16 +172,16 @@ class FanSliderOverlay : public tsl::Gui { for (int j = 0; j < 3; j++) { result << arr[j] << ", "; } - if (i != initialData.size() -1) - result << arr[3] << "], ["; + if (i != initialData.size() - 1) + result << arr[3] << "], ["; else result << arr[3] << "]]\"\""; - } return result.str(); } - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (keysDown & KEY_B) { tsl::goBack(); return true; diff --git a/source/HelpOverlay.hpp b/source/HelpOverlay.hpp index 5ee81bce..01635c4f 100644 --- a/source/HelpOverlay.hpp +++ b/source/HelpOverlay.hpp @@ -1,27 +1,35 @@ +#pragma once + #include #include + class HelpOverlay : public tsl::Gui { private: std::string helpPath; public: - HelpOverlay(const std::string& helpPath) : helpPath(helpPath) {} - ~HelpOverlay() {} + HelpOverlay(const std::string& helpPath) + : helpPath(helpPath) + { + } + ~HelpOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("HelpOverlay"); std::pair textDataPair; - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int fontSize = 19; // Adjust the font size as needed + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int fontSize = 19; // Adjust the font size as needed - auto rootFrame = new tsl::elm::OverlayFrame("Help", "Uberhand Package","",false,"\uE0E1 Back "); + auto rootFrame = new tsl::elm::OverlayFrame("Help", "Uberhand Package", "", false, "\uE0E1 Back "); auto list = new tsl::elm::List(); if (!isFileOrDirectory(helpPath)) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("Text file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("Text file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize + lineHeight); rootFrame->setContent(list); return rootFrame; } else { @@ -29,17 +37,19 @@ class HelpOverlay : public tsl::Gui { std::string textdata = textDataPair.first; int textsize = textDataPair.second; if (!textdata.empty()) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * textsize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * textsize + lineHeight); rootFrame->setContent(list); return rootFrame; } } - return rootFrame; + return rootFrame; } - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (keysDown & KEY_B) { tsl::goBack(); return true; diff --git a/source/IniSection.hpp b/source/IniSection.hpp index 98ce65e2..7cea64e0 100644 --- a/source/IniSection.hpp +++ b/source/IniSection.hpp @@ -1,10 +1,14 @@ +#pragma once + +#include #include #include using IniKeyValue = std::unordered_map; using IniSectionInput = std::unordered_map; -IniSectionInput readIniFile(const std::string& filename) { +IniSectionInput readIniFile(const std::string& filename) +{ IniSectionInput iniData; std::ifstream inFile(filename); std::string line; @@ -33,7 +37,8 @@ IniSectionInput readIniFile(const std::string& filename) { } // Write the IniSectionInput structure back to a file -void writeIniFile(const std::string& filename, const IniSectionInput& iniData) { +void writeIniFile(const std::string& filename, const IniSectionInput& iniData) +{ std::ofstream outFile(filename); for (const auto& [section, kvPairs] : iniData) { outFile << "[" << section << "]\n"; @@ -46,26 +51,27 @@ void writeIniFile(const std::string& filename, const IniSectionInput& iniData) { } // Update values in the INI data -void updateIniData(IniSectionInput& iniData, const IniSectionInput& updates, bool remove=false) { +void updateIniData(IniSectionInput& iniData, const IniSectionInput& updates, bool remove = false) +{ if (remove) { for (const auto& [section, kvPairs] : updates) { for (const auto& [key, value] : kvPairs) { - //log(iniData[section][key]); - iniData[section].erase(key); + //log(iniData[section][key]); + iniData[section].erase(key); } } } else { for (const auto& [section, kvPairs] : updates) { for (const auto& [key, value] : kvPairs) { - //log(iniData[section][key]); - iniData[section][key] = value; + //log(iniData[section][key]); + iniData[section][key] = value; } } } } - -std::vector splitSections(const std::string& str) { +std::vector splitSections(const std::string& str) +{ std::vector result; std::string temp; size_t pos = 0, lastPos = 0; @@ -83,8 +89,8 @@ std::vector splitSections(const std::string& str) { return result; } - -IniSectionInput parseDesiredData(const std::string& input) { +IniSectionInput parseDesiredData(const std::string& input) +{ IniSectionInput desiredData; std::vector sections = splitSections(input); diff --git a/source/JsonInfoOverlay.hpp b/source/JsonInfoOverlay.hpp index aead7cdf..f375fde8 100644 --- a/source/JsonInfoOverlay.hpp +++ b/source/JsonInfoOverlay.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include @@ -7,23 +9,29 @@ class JsonInfoOverlay : public tsl::Gui { std::string kipPath = "/atmosphere/kips/loader.kip"; public: - JsonInfoOverlay(const std::string& jsonPath, const std::string& specficKey) : jsonPath(jsonPath), specficKey(specficKey) {} - ~JsonInfoOverlay() {} + JsonInfoOverlay(const std::string& jsonPath, const std::string& specficKey) + : jsonPath(jsonPath) + , specficKey(specficKey) + { + } + ~JsonInfoOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("JsonInfoOverlay"); std::pair textDataPair; - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int fontSize = 19; // Adjust the font size as needed + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int fontSize = 19; // Adjust the font size as needed - auto rootFrame = new tsl::elm::OverlayFrame(specficKey, "Uberhand Package","",false,"\uE0E1 Back \uE0E0 Apply "); + auto rootFrame = new tsl::elm::OverlayFrame(specficKey, "Uberhand Package", "", false, "\uE0E1 Back \uE0E0 Apply "); auto list = new tsl::elm::List(); if (!isFileOrDirectory(jsonPath)) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("JSON file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("JSON file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize + lineHeight); rootFrame->setContent(list); return rootFrame; } else { @@ -31,18 +39,20 @@ class JsonInfoOverlay : public tsl::Gui { std::string textdata = textDataPair.first; int textsize = textDataPair.second; if (!textdata.empty()) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * textsize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * textsize + lineHeight); rootFrame->setContent(list); } } return rootFrame; } - std::map parseJson (const std::string& jsonPath, const std::string& selectedItem, std::vector offsets = {"32","48","16","36","52","64","56","68","60","76"}) { + std::map parseJson(const std::string& jsonPath, const std::string& selectedItem, std::vector offsets = { "32", "48", "16", "36", "52", "64", "56", "68", "60", "76" }) + { - std::map newKipdata; + std::map newKipdata; const std::string CUST = "43555354"; std::vector offsetStrs = findHexDataOffsets(kipPath, CUST); @@ -54,29 +64,36 @@ class JsonInfoOverlay : public tsl::Gui { json_t* item = json_array_get(jsonData, i); json_t* keyValue = json_object_get(item, "name"); // + 2 to skip name and t_offsets - if (json_object_size(item) != offsets.size() + 2) { return newKipdata; } + if (json_object_size(item) != offsets.size() + 2) { + return newKipdata; + } if (json_string_value(keyValue) == selectedItem) { - const char *key; - json_t *value; + const char* key; + json_t* value; int j = 0; json_t* t_offsettsJ = json_object_get(item, "t_offsets"); if (t_offsettsJ) { offsets = parseString(json_string_value(t_offsettsJ), ','); } - + if (!offsetStrs.empty()) { - for(auto& offset : offsets) { + for (auto& offset : offsets) { offset = std::to_string(std::stoul(offset) + offsetStrs[0]); // count from "C" letter } } - json_object_foreach(item, key, value) { + json_object_foreach(item, key, value) + { if (strcmp(key, "name") != 0 && strcmp(key, "t_offsets") != 0) { std::string valStr = json_string_value(value); size_t spacePos = valStr.find(' '); - if (spacePos != 0) {valStr.resize(spacePos);} + if (spacePos != 0) { + valStr.resize(spacePos); + } // if not a flag or state - convert to KHz/Microvolts - if (valStr.length() >= 3) { valStr = std::to_string(std::stoi(valStr) * 1000); } + if (valStr.length() >= 3) { + valStr = std::to_string(std::stoi(valStr) * 1000); + } newKipdata.emplace(offsets[j], decimalToReversedHex(valStr)); j++; } @@ -88,18 +105,19 @@ class JsonInfoOverlay : public tsl::Gui { return newKipdata; } - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (keysDown & KEY_B) { tsl::goBack(); return true; } - if (keysDown & KEY_A) { - std::map offsetData = parseJson(jsonPath, specficKey); + if (keysDown & KEY_A) { + std::map offsetData = parseJson(jsonPath, specficKey); hexEditByOffsetF(kipPath, offsetData); applied = true; tsl::goBack(); return true; - } + } return false; } }; \ No newline at end of file diff --git a/source/KipInfoOverlay.hpp b/source/KipInfoOverlay.hpp index 517cb10d..23b0b0f9 100644 --- a/source/KipInfoOverlay.hpp +++ b/source/KipInfoOverlay.hpp @@ -1,3 +1,5 @@ +#pragma once + #include #include @@ -8,20 +10,30 @@ class KipInfoOverlay : public tsl::Gui { bool isFirstPage = true; public: - KipInfoOverlay(const std::vector& kipInfoCommand) : kipInfoCommand(kipInfoCommand), showBackup(true) {} - KipInfoOverlay(const std::vector& kipInfoCommand, bool showBackup, bool isFirstPage = true) : kipInfoCommand(kipInfoCommand), showBackup(showBackup), isFirstPage(isFirstPage) {} - ~KipInfoOverlay() {} + KipInfoOverlay(const std::vector& kipInfoCommand) + : kipInfoCommand(kipInfoCommand) + , showBackup(true) + { + } + KipInfoOverlay(const std::vector& kipInfoCommand, bool showBackup, bool isFirstPage = true) + : kipInfoCommand(kipInfoCommand) + , showBackup(showBackup) + , isFirstPage(isFirstPage) + { + } + ~KipInfoOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("KipInfoOverlay"); std::pair textDataPair; - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int fontSize = 19; // Adjust the font size as needed + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int fontSize = 19; // Adjust the font size as needed std::string footer; if (showBackup) { - if (kipInfoCommand.size() > 3){ + if (kipInfoCommand.size() > 3) { hasPages = true; if (isFirstPage) footer = "\uE0E0 Apply \uE0E2 Delete \uE0EE Page 2"; @@ -35,35 +47,36 @@ class KipInfoOverlay : public tsl::Gui { hasPages = true; if (isFirstPage) footer = "\uE0E1 Back \uE0EE Page 2"; - else + else footer = "\uE0E1 Back \uE0ED Page 1"; } else { footer = "\uE0E1 Back"; } } - + auto rootFrame = new tsl::elm::OverlayFrame("Kip Management", "Uberhand Package", "", false, footer); auto list = new tsl::elm::List(); if (!showBackup) { textDataPair = dispCustData(kipInfoCommand[isFirstPage ? 1 : 2]); - } - else { + } else { textDataPair = dispCustData(kipInfoCommand[isFirstPage ? 2 : 3], kipInfoCommand[1]); } std::string textdata = textDataPair.first; int textsize = textDataPair.second; if (!textdata.empty()) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * textsize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * textsize + lineHeight); rootFrame->setContent(list); } - return rootFrame; + return rootFrame; } - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (!isFirstPage && (keysDown & KEY_B)) { tsl::goBack(); tsl::goBack(); @@ -74,23 +87,23 @@ class KipInfoOverlay : public tsl::Gui { return true; } if (showBackup && (keysDown & KEY_A)) { - copyFileOrDirectory(this->kipInfoCommand[1], "/atmosphere/kips/loader.kip"); - applied = true; - tsl::goBack(); - return true; + copyFileOrDirectory(this->kipInfoCommand[1], "/atmosphere/kips/loader.kip"); + applied = true; + tsl::goBack(); + return true; } if (showBackup && (keysDown & KEY_X)) { - deleteFileOrDirectory(this->kipInfoCommand[1]); - tsl::goBack(); - applied = false; - deleted = true; - return true; + deleteFileOrDirectory(this->kipInfoCommand[1]); + tsl::goBack(); + applied = false; + deleted = true; + return true; } if (hasPages && isFirstPage && (keysDown & KEY_DRIGHT)) { - tsl::changeTo(kipInfoCommand, showBackup, false); + tsl::changeTo(kipInfoCommand, showBackup, false); } if (hasPages && !isFirstPage && (keysDown & KEY_DLEFT)) { - tsl::goBack(); + tsl::goBack(); } return false; } diff --git a/source/debug_funcs.hpp b/source/debug_funcs.hpp index dc90b343..c1ae8cef 100644 --- a/source/debug_funcs.hpp +++ b/source/debug_funcs.hpp @@ -1,16 +1,18 @@ #pragma once + +#include + #include +#include #include #include -#include -#include const char* logPath = "sdmc:/config/uberhand/log.txt"; -char logTimeBuffer[std::size("yyyy-mm-dd hh:mm:ss")]{ 0 }; +char logTimeBuffer[std::size("yyyy-mm-dd hh:mm:ss")] { 0 }; -__attribute__((__format__(__printf__, 1, 2))) -void log(const char* format, ...) noexcept { +__attribute__((__format__(__printf__, 1, 2))) void log(const char* format, ...) noexcept +{ FILE* logFile = fopen(logPath, "a"); if (logFile == nullptr) { fprintf(stderr, "Failed to open log file: %s", logPath); diff --git a/source/download_funcs.hpp b/source/download_funcs.hpp index 8c67d69d..dad2e642 100644 --- a/source/download_funcs.hpp +++ b/source/download_funcs.hpp @@ -1,35 +1,41 @@ #pragma once -#include + +#include "debug_funcs.hpp" +#include "get_funcs.hpp" +#include "json_funcs.hpp" +#include "path_funcs.hpp" +#include "string_funcs.hpp" + #include #include #include -#include "string_funcs.hpp" -#include "get_funcs.hpp" -#include "path_funcs.hpp" -#include "debug_funcs.hpp" -#include "json_funcs.hpp" + +#include const char* userAgent = "Mozilla/5.0 (Nintendo Switch; WebApplet) AppleWebKit/609.4 (KHTML, like Gecko) NF/6.0.2.21.3 NintendoBrowser/5.1.0.22474"; -size_t writeCallbackFile(void* contents, size_t size, size_t nmemb, FILE* file) { +size_t writeCallbackFile(void* contents, size_t size, size_t nmemb, FILE* file) +{ // Callback function to write received data to a file size_t written = fwrite(contents, size, nmemb, file); return written; } -size_t writeCallbackJson(void* contents, size_t size, size_t nmemb, std::string* s) { +size_t writeCallbackJson(void* contents, size_t size, size_t nmemb, std::string* s) +{ size_t newLength = size * nmemb; try { s->append((char*)contents, newLength); - } catch(std::bad_alloc &e) { + } catch (std::bad_alloc& e) { // Handle memory allocation exceptions return 0; } return newLength; } -SafeJson loadJsonFromUrl(const std::string& url) { - CURL *curl; +SafeJson loadJsonFromUrl(const std::string& url) +{ + CURL* curl; CURLcode res; std::string readBuffer; readBuffer.reserve(5 * 1024); @@ -37,7 +43,7 @@ SafeJson loadJsonFromUrl(const std::string& url) { curl_global_init(CURL_GLOBAL_DEFAULT); curl = curl_easy_init(); - if(curl) { + if (curl) { curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeCallbackJson); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); @@ -45,7 +51,7 @@ SafeJson loadJsonFromUrl(const std::string& url) { res = curl_easy_perform(curl); curl_easy_cleanup(curl); - if(res != CURLE_OK) { + if (res != CURLE_OK) { fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res)); return nullptr; } @@ -69,37 +75,40 @@ struct progress { tsl::elm::ListItem* listItem; int totalCommands; int curProgress; -};; +}; +; -static size_t progress_callback(void *clientp, +static size_t progress_callback(void* clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, - curl_off_t ulnow) { + curl_off_t ulnow) +{ if (dltotal <= 0) { //log("Download progress: Unknown total size"); return 0; } - struct progress *memory = static_cast(clientp); + struct progress* memory = static_cast(clientp); tsl::elm::ListItem* listItem = memory->listItem; int totalCommands = memory->totalCommands; int curProgress = memory->curProgress; // Calculate download percentage - int progress = curProgress + ((static_cast(dlnow)*100) / (static_cast(dltotal)*totalCommands)); + int progress = curProgress + ((static_cast(dlnow) * 100) / (static_cast(dltotal) * totalCommands)); std::string progressStr = std::to_string(progress) + "%"; if (listItem->getValue() != progressStr) { listItem->setValue(progressStr, tsl::PredefinedColors::Green); } - + return 0; } -bool downloadFile(const std::string& url, const std::string& toDestination, tsl::elm::ListItem* listItem = nullptr, int totalCommands = -1, int curProgress = -1) { +bool downloadFile(const std::string& url, const std::string& toDestination, tsl::elm::ListItem* listItem = nullptr, int totalCommands = -1, int curProgress = -1) +{ std::string destination = toDestination; // Check if the destination ends with "/" if (destination.back() == '/') { createDirectory(destination); - + // Extract the filename from the URL size_t lastSlash = url.find_last_of('/'); if (lastSlash != std::string::npos) { @@ -110,9 +119,8 @@ bool downloadFile(const std::string& url, const std::string& toDestination, tsl: return false; } } else { - createDirectory(destination.substr(0, destination.find_last_of('/'))+"/"); + createDirectory(destination.substr(0, destination.find_last_of('/')) + "/"); } - const int MAX_RETRIES = 3; int retryCount = 0; @@ -134,7 +142,7 @@ bool downloadFile(const std::string& url, const std::string& toDestination, tsl: log("Error initializing curl after multiple retries."); return false; } - + FILE* file = fopen(destination.c_str(), "wb"); if (!file) { log("Error opening file: %s", destination.c_str()); @@ -184,9 +192,9 @@ bool downloadFile(const std::string& url, const std::string& toDestination, tsl: return true; } - -bool unzipFile(const std::string& zipFilePath, const std::string& toDestination, tsl::elm::ListItem* listItem = nullptr, int totalCommands = -1, int curProgress = -1) { - zzip_error_t errorCode{ ZZIP_NO_ERROR }; +bool unzipFile(const std::string& zipFilePath, const std::string& toDestination, tsl::elm::ListItem* listItem = nullptr, int totalCommands = -1, int curProgress = -1) +{ + zzip_error_t errorCode { ZZIP_NO_ERROR }; ZZIP_DIR* dir = zzip_dir_open(zipFilePath.c_str(), &errorCode); if (!dir) { log("Error opening file: %s; error: %s", zipFilePath.c_str(), zzip_strerror(errorCode)); @@ -209,7 +217,8 @@ bool unzipFile(const std::string& zipFilePath, const std::string& toDestination, zzip_rewinddir(dir); while (zzip_dir_read(dir, &entry)) { - if (entry.d_name[0] == '\0') continue; // Skip empty records + if (entry.d_name[0] == '\0') + continue; // Skip empty records currentFile++; @@ -218,7 +227,7 @@ bool unzipFile(const std::string& zipFilePath, const std::string& toDestination, if (totalCommands != -1) { // Calculate the percentage completion and add it to the log string - std::string progress_str = std::to_string(curProgress + ((currentFile*100) / (totalFiles*totalCommands))) + "%"; + std::string progress_str = std::to_string(curProgress + ((currentFile * 100) / (totalFiles * totalCommands))) + "%"; if (listItem->getValue() != progress_str.c_str()) { listItem->setValue(progress_str.c_str(), tsl::PredefinedColors::Green); } diff --git a/source/get_funcs.hpp b/source/get_funcs.hpp index b8875989..6ac55fab 100644 --- a/source/get_funcs.hpp +++ b/source/get_funcs.hpp @@ -2,13 +2,15 @@ #include "debug_funcs.hpp" #include "json_funcs.hpp" + #include #include #include -#include #include #include +#include + // Get functions // Overlay Module settings @@ -16,7 +18,8 @@ constexpr int OverlayLoaderModuleId = 348; constexpr Result ResultSuccess = MAKERESULT(0, 0); constexpr Result ResultParseError = MAKERESULT(OverlayLoaderModuleId, 1); -std::tuple getOverlayInfo(const std::string& filePath) { +std::tuple getOverlayInfo(const std::string& filePath) +{ FILE* file = fopen(filePath.c_str(), "r"); NroHeader nroHeader; @@ -43,7 +46,7 @@ std::tuple getOverlayInfo(const std::string& f fclose(file); return { ResultParseError, "", "" }; } - + fclose(file); // Return overlay information @@ -54,9 +57,9 @@ std::tuple getOverlayInfo(const std::string& f }; } - // Function to read the content of a file -std::string getFileContents(const std::string& filePath) { +std::string getFileContents(const std::string& filePath) +{ std::string content; FILE* file = fopen(filePath.c_str(), "rb"); if (file) { @@ -73,19 +76,21 @@ std::string getFileContents(const std::string& filePath) { return content; } - -std::string getFileNameFromURL(const std::string& url) { +std::string getFileNameFromURL(const std::string& url) +{ size_t lastSlash = url.find_last_of('/'); if (lastSlash != std::string::npos) return url.substr(lastSlash + 1); return ""; } -std::string getDestinationPath(const std::string& destinationDir, const std::string& fileName) { +std::string getDestinationPath(const std::string& destinationDir, const std::string& fileName) +{ return destinationDir + "/" + fileName; } -std::string getValueFromLine(const std::string& line) { +std::string getValueFromLine(const std::string& line) +{ std::size_t equalsPos = line.find('='); if (equalsPos != std::string::npos) { std::string value = line.substr(equalsPos + 1); @@ -94,8 +99,8 @@ std::string getValueFromLine(const std::string& line) { return ""; } - -std::string getNameFromPath(const std::string& path) { +std::string getNameFromPath(const std::string& path) +{ size_t lastSlash = path.find_last_of('/'); if (lastSlash != std::string::npos) { std::string name = path.substr(lastSlash + 1); @@ -112,7 +117,8 @@ std::string getNameFromPath(const std::string& path) { return path; } -std::string getParentDirFromPath(const std::string& path) { +std::string getParentDirFromPath(const std::string& path) +{ size_t lastSlash = path.find_last_of('/'); if (lastSlash != std::string::npos) { std::string parentDir = path.substr(0, lastSlash + 1); @@ -121,7 +127,8 @@ std::string getParentDirFromPath(const std::string& path) { return path; } -std::string getParentDirNameFromPath(const std::string& path) { +std::string getParentDirNameFromPath(const std::string& path) +{ // Find the position of the last occurrence of the directory separator '/' std::size_t lastSlashPos = removeEndingSlash(path).rfind('/'); @@ -150,7 +157,8 @@ std::string getParentDirNameFromPath(const std::string& path) { return ""; } -std::string getNameWithoutPrefix(std::string Name) { +std::string getNameWithoutPrefix(std::string Name) +{ std::regex pattern("^(\\d{1,2})_"); std::smatch matches; if (std::regex_search(Name, matches, pattern)) { @@ -159,7 +167,8 @@ std::string getNameWithoutPrefix(std::string Name) { return Name; } -std::vector getSubdirectories(const std::string& directoryPath) { +std::vector getSubdirectories(const std::string& directoryPath) +{ std::vector subdirectories; DIR* dir = opendir(directoryPath.c_str()); @@ -185,7 +194,8 @@ std::vector getSubdirectories(const std::string& directoryPath) { return subdirectories; } -std::vector getFilesListFromDirectory(const std::string& directoryPath) { +std::vector getFilesListFromDirectory(const std::string& directoryPath) +{ std::vector fileList; DIR* dir = opendir(directoryPath.c_str()); @@ -215,9 +225,9 @@ std::vector getFilesListFromDirectory(const std::string& directoryP return fileList; } - // get files list for file patterns and folders list for folder patterns -std::vector getFilesListByWildcard(const std::string& pathPattern) { +std::vector getFilesListByWildcard(const std::string& pathPattern) +{ std::string dirPath = ""; std::string wildcard = ""; @@ -243,7 +253,7 @@ std::vector getFilesListByWildcard(const std::string& pathPattern) bool isFolderWildcard = wildcard.back() == '/'; if (isFolderWildcard) { - wildcard.resize(wildcard.size() - 1); // Remove the trailing slash + wildcard.resize(wildcard.size() - 1); // Remove the trailing slash } //log("isFolderWildcard: " + std::to_string(isFolderWildcard)); @@ -264,7 +274,7 @@ std::vector getFilesListByWildcard(const std::string& pathPattern) if (isFolderWildcard && isEntryDirectory && fnmatch(wildcard.c_str(), entryName.c_str(), FNM_NOESCAPE) == 0) { if (entryName != "." && entryName != "..") { - fileList.push_back(entryPath+"/"); + fileList.push_back(entryPath + "/"); } } else if (!isFolderWildcard && !isEntryDirectory) { std::size_t wildcardPos = wildcard.find('*'); @@ -293,8 +303,8 @@ std::vector getFilesListByWildcard(const std::string& pathPattern) return fileList; } - -std::vector getFilesListByWildcards(const std::string& pathPattern) { +std::vector getFilesListByWildcards(const std::string& pathPattern) +{ std::vector fileList; // Check if the pattern contains multiple wildcards @@ -330,9 +340,8 @@ std::vector getFilesListByWildcards(const std::string& pathPattern) return fileList; } - - -std::string replacePlaceholder(const std::string& input, const std::string& placeholder, const std::string& replacement) { +std::string replacePlaceholder(const std::string& input, const std::string& placeholder, const std::string& replacement) +{ std::string result = input; std::size_t pos = result.find(placeholder); if (pos != std::string::npos) { @@ -341,7 +350,8 @@ std::string replacePlaceholder(const std::string& input, const std::string& plac return result; } -std::string replaceJsonSourcePlaceholder(const std::string& placeholder, const std::string& jsonPath, std::string searchString = "{json_data(") { +std::string replaceJsonSourcePlaceholder(const std::string& placeholder, const std::string& jsonPath, std::string searchString = "{json_data(") +{ // Load JSON data from the provided file json_error_t error; SafeJson root = json_load_file(jsonPath.c_str(), 0, &error); @@ -349,11 +359,11 @@ std::string replaceJsonSourcePlaceholder(const std::string& placeholder, const s if (!root) { // Handle JSON parsing error // printf("JSON parsing error: %s\n", error.text); - return placeholder; // Return the original placeholder if JSON parsing fails + return placeholder; // Return the original placeholder if JSON parsing fails } std::string replacement = placeholder; - + std::size_t startPos = replacement.find(searchString); std::size_t endPos = replacement.find(")}"); if (startPos != std::string::npos && endPos != std::string::npos && endPos > startPos) { @@ -388,13 +398,13 @@ std::string replaceJsonSourcePlaceholder(const std::string& placeholder, const s } else { // Handle invalid JSON array index // printf("Invalid JSON array index: %s\n", key.c_str()); - return placeholder; // Return the original placeholder if JSON array index is invalid + return placeholder; // Return the original placeholder if JSON array index is invalid } } } else { // Handle invalid JSON structure or key // printf("Invalid JSON structure or key: %s\n", key.c_str()); - return placeholder; // Return the original placeholder if JSON structure or key is invalid + return placeholder; // Return the original placeholder if JSON structure or key is invalid } } @@ -408,12 +418,11 @@ std::string replaceJsonSourcePlaceholder(const std::string& placeholder, const s return replacement; } - - -std::vector> getModifyCommands(const std::vector>& commands, const std::string& file, bool toggle = false, bool on = true, bool usingJsonSource = false) { +std::vector> getModifyCommands(const std::vector>& commands, const std::string& file, bool toggle = false, bool on = true, bool usingJsonSource = false) +{ std::vector> modifiedCommands; std::string jsonPath, replacement; - + bool addCommands = false; for (const auto& cmd : commands) { if (cmd.size() > 1) { @@ -432,7 +441,7 @@ std::vector> getModifyCommands(const std::vector modifiedCmd = cmd; @@ -447,32 +456,31 @@ std::vector> getModifyCommands(const std::vector startPos) { - // std::string placeholder = "*"; - // std::string replacement = arg.substr(startPos, endPos - startPos + 2); - // size_t placeholderPos = replacement.find(placeholder); - // if (placeholderPos != std::string::npos) { - // replacement.replace(placeholderPos, placeholder.length(), file); - // //arg.replace(startPos, endPos - startPos + 2, replacement); - // } - // - // replacement = replaceJsonSourcePlaceholder(replacement, jsonPath, true); - // //log2("replacement: "+replacement); - // //log2("pre-arg: "+arg); - // arg.replace(startPos, endPos - startPos + 2, replacement); - // } + //} else if (arg.find("{json_source(") != std::string::npos) { + // size_t startPos = arg.find("{json_source("); + // size_t endPos = arg.find(")}"); + // if (endPos != std::string::npos && endPos > startPos) { + // std::string placeholder = "*"; + // std::string replacement = arg.substr(startPos, endPos - startPos + 2); + // size_t placeholderPos = replacement.find(placeholder); + // if (placeholderPos != std::string::npos) { + // replacement.replace(placeholderPos, placeholder.length(), file); + // //arg.replace(startPos, endPos - startPos + 2, replacement); + // } + // + // replacement = replaceJsonSourcePlaceholder(replacement, jsonPath, true); + // //log2("replacement: "+replacement); + // //log2("pre-arg: "+arg); + // arg.replace(startPos, endPos - startPos + 2, replacement); + // } } else if (usingJsonSource && (arg.find("{json_source(") != std::string::npos)) { std::string countStr = file; - + // log(std::string("count: ")+countStr); // log(std::string("pre arg: ") + arg); arg = replacePlaceholder(arg, "*", file); // log(std::string("post arg: ") + arg); - size_t startPos = arg.find("{json_source("); size_t endPos = arg.find(")}"); if (endPos != std::string::npos && endPos > startPos) { @@ -484,13 +492,12 @@ std::vector> getModifyCommands(const std::vector startPos) { @@ -499,13 +506,12 @@ std::vector> getModifyCommands(const std::vector startPos) { diff --git a/source/hex_funcs.hpp b/source/hex_funcs.hpp index 9a946533..5a829a7e 100644 --- a/source/hex_funcs.hpp +++ b/source/hex_funcs.hpp @@ -1,13 +1,16 @@ #pragma once -#include -#include + +#include // Added for stat + #include #include // Added for FILE and fopen #include // Added for std::memcmp -#include // Added for stat +#include +#include // Hex-editing commands -std::string asciiToHex(const std::string& asciiStr) { +std::string asciiToHex(const std::string& asciiStr) +{ std::string hexStr; hexStr.reserve(asciiStr.length() * 2); // Reserve space for the hexadecimal string @@ -27,14 +30,16 @@ std::string asciiToHex(const std::string& asciiStr) { return hexStr; } -std::string decimalToHex(const std::string& decimalStr) { +std::string decimalToHex(const std::string& decimalStr) +{ // assumes the decimal is a 32-bit integer - std::string hexadecimal = (std::stringstream{} << std::hex << std::setw(8) << std::setfill('0') << std::stoi(decimalStr)).str(); + std::string hexadecimal = (std::stringstream {} << std::hex << std::setw(8) << std::setfill('0') << std::stoi(decimalStr)).str(); return hexadecimal; } -std::string decimalToReversedHex(const std::string& decimalStr, int order = 2) { +std::string decimalToReversedHex(const std::string& decimalStr, int order = 2) +{ std::string hexadecimal = decimalToHex(decimalStr); // Reverse the hexadecimal string in groups of order @@ -49,7 +54,8 @@ std::string decimalToReversedHex(const std::string& decimalStr, int order = 2) { std::vector findHexDataOffsetsF(FILE* const file, const std::string& hexData); -std::vector findHexDataOffsets(const std::string& filePath, const std::string& hexData) { +std::vector findHexDataOffsets(const std::string& filePath, const std::string& hexData) +{ // Open the file for reading in binary mode FILE* file = fopen(filePath.c_str(), "rb"); if (!file) { @@ -71,7 +77,8 @@ std::vector findHexDataOffsets(const std::string& filePath, const std::s return offsets; } -std::vector findHexDataOffsetsF(FILE* const file, const std::string& hexData) { +std::vector findHexDataOffsetsF(FILE* const file, const std::string& hexData) +{ // Convert the hex data string to binary data std::vector binaryData; for (std::size_t i = 0; i < hexData.length(); i += 2) { @@ -101,7 +108,8 @@ std::vector findHexDataOffsetsF(FILE* const file, const std::string& hex std::string readHexDataAtOffsetF(FILE* const file, const size_t offset, size_t length); -std::string readHexDataAtOffset(const std::string& filePath, const std::string& hexData, const size_t offsetFromData, size_t length) { +std::string readHexDataAtOffset(const std::string& filePath, const std::string& hexData, const size_t offsetFromData, size_t length) +{ // log("Entered readHexDataAtOffset"); // Open the file for reading in binary mode @@ -125,8 +133,9 @@ std::string readHexDataAtOffset(const std::string& filePath, const std::string& return result; } -FILE* openFile(const std::string& filePath) { - +FILE* openFile(const std::string& filePath) +{ + // Open the file for reading in binary mode FILE* file = fopen(filePath.c_str(), "rb"); if (!file) { @@ -136,7 +145,8 @@ FILE* openFile(const std::string& filePath) { return file; } -long findCustOffset(FILE* const file) { +long findCustOffset(FILE* const file) +{ const std::vector dataOffsets = findHexDataOffsetsF(file, "43555354"); if (dataOffsets.empty()) { log("readHexDataAtOffset: data \"%s\" not found.", "CUST"); @@ -145,9 +155,10 @@ long findCustOffset(FILE* const file) { return dataOffsets[0]; } -std::string readHexDataAtOffset(FILE* const file, const std::string& hexData, const size_t offsetFromData, size_t length, int custOffset = -1) { +std::string readHexDataAtOffset(FILE* const file, const std::string& hexData, const size_t offsetFromData, size_t length, int custOffset = -1) +{ // log("Entered readHexDataAtOffset"); - + if (!file) { log("Failed to open the file."); return ""; @@ -170,7 +181,8 @@ std::string readHexDataAtOffset(FILE* const file, const std::string& hexData, co return result; } -std::string readHexDataAtOffsetF(FILE* const file, const size_t offset, const size_t length) { +std::string readHexDataAtOffsetF(FILE* const file, const size_t offset, const size_t length) +{ // log("Entered readHexDataAtOffsetF"); if (fseek(file, offset, SEEK_SET) != 0) { @@ -203,7 +215,8 @@ std::string readHexDataAtOffsetF(FILE* const file, const size_t offset, const si return result; } -bool hexEditByOffset(const std::string& filePath, const size_t offset, const std::string& hexData) { +bool hexEditByOffset(const std::string& filePath, const size_t offset, const std::string& hexData) +{ // Open the file for reading and writing in binary mode FILE* file = fopen(filePath.c_str(), "rb+"); if (!file) { @@ -256,7 +269,8 @@ bool hexEditByOffset(const std::string& filePath, const size_t offset, const std } // Is used when mutiple write iterrations are required to reduce the number of file open/close requests -bool hexEditByOffsetF(const std::string& filePath, const std::map & data) { +bool hexEditByOffsetF(const std::string& filePath, const std::map& data) +{ // Open the file for reading and writing in binary mode FILE* file = fopen(filePath.c_str(), "rb+"); @@ -265,8 +279,8 @@ bool hexEditByOffsetF(const std::string& filePath, const std::map offsets = findHexDataOffsets(filePath, hexDataToReplace); if (!offsets.empty()) { if (occurrence == "0") { @@ -327,8 +342,7 @@ bool hexEditFindReplace(const std::string& filePath, const std::string& hexDataT //log("hexDataReplacement: "+hexDataReplacement); hexEditByOffset(filePath, offset, hexDataReplacement); } - } - else { + } else { // Convert the occurrence string to an integer std::size_t index = std::stoul(occurrence); if (index > 0 && index <= offsets.size()) { @@ -337,8 +351,7 @@ bool hexEditFindReplace(const std::string& filePath, const std::string& hexDataT //log("offsetStr: "+offsetStr); //log("hexDataReplacement: "+hexDataReplacement); hexEditByOffset(filePath, offset, hexDataReplacement); - } - else { + } else { return false; // Invalid occurrence/index specified log("Invalid occurrence/index specified."); @@ -346,28 +359,28 @@ bool hexEditFindReplace(const std::string& filePath, const std::string& hexDataT } return true; //std::cout << "Hex data replaced successfully." << std::endl; - } - else { + } else { return false; log("Hex data to replace not found."); } } -bool hexEditCustOffset(const std::string& filePath, const size_t offsetFromCust, const std::string& hexDataReplacement) { +bool hexEditCustOffset(const std::string& filePath, const size_t offsetFromCust, const std::string& hexDataReplacement) +{ const std::string CUST = "43555354"; const std::vector custOffsets = findHexDataOffsets(filePath, CUST); if (!custOffsets.empty()) { const size_t offset = offsetFromCust + custOffsets[0]; // count from "C" letter hexEditByOffset(filePath, offset, hexDataReplacement); - } - else { + } else { return false; log("CUST not found."); } return true; } -int reversedHexToInt(const std::string& hex_str) { +int reversedHexToInt(const std::string& hex_str) +{ std::string reversedHex; reversedHex.reserve(hex_str.size()); diff --git a/source/ini_funcs.hpp b/source/ini_funcs.hpp index 039a2122..88104292 100644 --- a/source/ini_funcs.hpp +++ b/source/ini_funcs.hpp @@ -1,16 +1,19 @@ #pragma once + +#include "IniSection.hpp" +#include "debug_funcs.hpp" + #include -#include // For FILE*, fopen(), fclose(), fprintf(), etc. -#include // For std::string, strlen(), etc. -#include // For std::string -#include // For std::vector -#include // For std::map -#include // For std::istringstream + #include // For std::remove_if -#include // For ::isspace +#include // For ::isspace +#include // For FILE*, fopen(), fclose(), fprintf(), etc. +#include // For std::string, strlen(), etc. #include -#include "debug_funcs.hpp" -#include "IniSection.hpp" +#include // For std::map +#include // For std::istringstream +#include // For std::string +#include // For std::vector // Ini Functions @@ -19,11 +22,12 @@ struct PackageHeader { std::string creator; std::string github; std::string about; - bool enableConfigNav{ false }; - bool showCurInMenu { false }; + bool enableConfigNav { false }; + bool showCurInMenu { false }; std::string checkKipVersion; }; -PackageHeader getPackageHeaderFromIni(const std::string& filePath) { +PackageHeader getPackageHeaderFromIni(const std::string& filePath) +{ PackageHeader packageHeader; FILE* file = fopen(filePath.c_str(), "r"); if (file == nullptr) { @@ -43,10 +47,9 @@ PackageHeader getPackageHeaderFromIni(const std::string& filePath) { const std::string aboutPrefix = ";about="; const std::string repoPrefix = ";github="; const std::string configNavMarker = ";enableConfigNav"; - const std::string showCurMarker = ";showCurInMenu"; + const std::string showCurMarker = ";showCurInMenu"; const std::string kipVerMarker = ";kipVer="; - while (fgets(line, sizeof(line), file)) { if (line[0] != ';') { // Header ended. Skip further parsing break; @@ -116,7 +119,6 @@ PackageHeader getPackageHeaderFromIni(const std::string& filePath) { if (showCurMarker == strLine.substr(0, showCurMarker.length())) { packageHeader.showCurInMenu = true; - } size_t repoPos = strLine.find(repoPrefix); @@ -138,17 +140,16 @@ PackageHeader getPackageHeaderFromIni(const std::string& filePath) { } } - - fclose(file); - + return packageHeader; } using KeyValueData = std::map; using IniData = std::map; -static IniData parseIni(std::istream& str) { +static IniData parseIni(std::istream& str) +{ IniData iniData; std::string section = ""; @@ -161,7 +162,7 @@ static IniData parseIni(std::istream& str) { } else if (line[0] == '[' && line[line.size() - 1] == ']') { // Section section = line.substr(1, line.size() - 2); - iniData.emplace(section, KeyValueData{}); + iniData.emplace(section, KeyValueData {}); } else if (size_t equalsPos = line.find('='); equalsPos != std::string::npos) { // Key = Value std::string key = trim(line.substr(0, equalsPos)); @@ -177,7 +178,8 @@ static IniData parseIni(std::istream& str) { } // Custom utility function for parsing an ini file -IniData getParsedDataFromIniFile(const std::string& configIniPath) { +IniData getParsedDataFromIniFile(const std::string& configIniPath) +{ std::ifstream iniFile(configIniPath); return parseIni(iniFile); } @@ -209,11 +211,12 @@ bool isMarikoHWType() } } -std::vector>>> loadOptionsFromIni(const std::string& configIniPath, bool makeConfig = false) { +std::vector>>> loadOptionsFromIni(const std::string& configIniPath, bool makeConfig = false) +{ std::vector>>> options; FILE* configFile = fopen(configIniPath.c_str(), "r"); - if (!configFile ) { + if (!configFile) { // Write the default INI file FILE* configFileOut = fopen(configIniPath.c_str(), "w"); std::string commands; @@ -226,8 +229,7 @@ std::vector>>> loadO commands = ""; } fprintf(configFileOut, "%s", commands.c_str()); - - + fclose(configFileOut); configFile = fopen(configIniPath.c_str(), "r"); } @@ -241,7 +243,7 @@ std::vector>>> loadO while (fgets(line, sizeof(line), configFile)) { std::string trimmedLine = line; - trimmedLine.erase(trimmedLine.find_last_not_of("\r\n") + 1); // Remove trailing newline character + trimmedLine.erase(trimmedLine.find_last_not_of("\r\n") + 1); // Remove trailing newline character if (trimmedLine.empty() || trimmedLine[0] == '#') { // Skip empty lines and comment lines @@ -249,7 +251,7 @@ std::vector>>> loadO } else if (trimmedLine.starts_with("--")) { // Separator if (!currentOption.empty()) { // Store previous option and its commands - if(!skipCommand) { + if (!skipCommand) { options.emplace_back(std::move(currentOption), std::move(commands)); } commands.clear(); @@ -265,10 +267,10 @@ std::vector>>> loadO if ((name.substr(pos + 3) == "Mariko" && !isMariko) || (name.substr(pos + 3) == "Erista" && isMariko)) { continue; } - name = name.substr(0,pos); + name = name.substr(0, pos); } name = name.substr(start); - std::vector command{ "separator" }; + std::vector command { "separator" }; commands.push_back(std::move(command)); options.emplace_back(std::move(name), std::move(commands)); } else if (trimmedLine == "; Mariko") { @@ -277,18 +279,18 @@ std::vector>>> loadO } else if (trimmedLine == "; Erista") { skipCommand = (isMariko); continue; - if (trimmedLine == "; Help") {} + if (trimmedLine == "; Help") { } } else if (trimmedLine[0] == '[' && trimmedLine.back() == ']') { // New option section if (!currentOption.empty()) { - if(!skipCommand){ + if (!skipCommand) { // Store previous option and its commands options.emplace_back(std::move(currentOption), std::move(commands)); } commands.clear(); skipCommand = false; } - currentOption = trimmedLine.substr(1, trimmedLine.size() - 2); // Extract option name + currentOption = trimmedLine.substr(1, trimmedLine.size() - 2); // Extract option name } else if (!currentOption.empty()) { // Command line std::istringstream iss(trimmedLine); @@ -317,7 +319,7 @@ std::vector>>> loadO // Store the last option and its commands if (!currentOption.empty()) { - if(!skipCommand){ + if (!skipCommand) { options.emplace_back(std::move(currentOption), std::move(commands)); } } @@ -326,7 +328,8 @@ std::vector>>> loadO return options; } -void cleanIniFormatting(const std::string& filePath) { +void cleanIniFormatting(const std::string& filePath) +{ FILE* inputFile = fopen(filePath.c_str(), "r"); if (!inputFile) { // Failed to open the input file @@ -369,7 +372,6 @@ void cleanIniFormatting(const std::string& filePath) { rename(tempPath.c_str(), filePath.c_str()); } - /* 1. Get a data vector: data>> Open file @@ -393,7 +395,7 @@ Close file // // std::cerr << "Unable to open file: " << fileToEdit << " for writing\n"; // return; // } - + // for (const auto& [section, keys] : desiredData) { // file << "[" << section << "]\n"; // for (const auto& [key, value] : keys) { @@ -403,7 +405,8 @@ Close file // } // } -bool setIniFile(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredValue, const std::string& desiredNewKey) { +bool setIniFile(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredValue, const std::string& desiredNewKey) +{ FILE* configFile = fopen(fileToEdit.c_str(), "r"); if (!configFile) { // The INI file doesn't exist, create a new file and add the section and key-value pair @@ -438,14 +441,13 @@ bool setIniFile(const std::string& fileToEdit, const std::string& desiredSection // Check if the line represents a section if (trimmedLine[0] == '[' && trimmedLine[trimmedLine.length() - 1] == ']') { currentSection = removeQuotes(trim(std::string(trimmedLine.c_str() + 1, trimmedLine.length() - 2))); - + if (sectionFound && !keyFound && (desiredNewKey.empty())) { // Write the modified line with the desired key and value formattedDesiredValue = removeQuotes(desiredValue); fprintf(tempFile, "%s=%s\n", desiredKey.c_str(), formattedDesiredValue.c_str()); keyFound = true; } - } if (sectionFound && !keyFound && desiredNewKey.empty()) { @@ -477,16 +479,16 @@ bool setIniFile(const std::string& fileToEdit, const std::string& desiredSection continue; // Skip writing the original line } } - } - + } + fprintf(tempFile, "%s", line); } - + if (sectionFound && !keyFound && (desiredNewKey.empty())) { // Write the modified line with the desired key and value fprintf(tempFile, "%s=%s\n", desiredKey.c_str(), formattedDesiredValue.c_str()); } - + if (!sectionFound && !keyFound && desiredNewKey.empty()) { // The desired section doesn't exist, so create it and add the key-value pair fprintf(tempFile, "[%s]\n", desiredSection.c_str()); @@ -506,59 +508,63 @@ bool setIniFile(const std::string& fileToEdit, const std::string& desiredSection return false; } -bool setIniFileValue(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredValue) { +bool setIniFileValue(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredValue) +{ bool result = setIniFile(fileToEdit, desiredSection, desiredKey, desiredValue, ""); cleanIniFormatting(fileToEdit); return result; } -bool setIniFileKey(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredNewKey) { +bool setIniFileKey(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey, const std::string& desiredNewKey) +{ bool result = setIniFile(fileToEdit, desiredSection, desiredKey, "", desiredNewKey); cleanIniFormatting(fileToEdit); return result; } -bool removeIniFileKey(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey) { - std::ifstream file(fileToEdit); - std::string line, currentSection; - bool sectionFound = false; - std::vector newLines; +bool removeIniFileKey(const std::string& fileToEdit, const std::string& desiredSection, const std::string& desiredKey) +{ + std::ifstream file(fileToEdit); + std::string line, currentSection; + bool sectionFound = false; + std::vector newLines; - while (std::getline(file, line)) { - // Remove leading and trailing whitespace - if (line.find_first_not_of(" \r\n") != std::string::npos) { - trimInPlace(line); - } + while (std::getline(file, line)) { + // Remove leading and trailing whitespace + if (line.find_first_not_of(" \r\n") != std::string::npos) { + trimInPlace(line); + } - if (!line.empty()) { - if (line[0] == '[' && line.back() == ']') { - currentSection = line.substr(1, line.length() - 2); - sectionFound = (currentSection == desiredSection); - } else if (sectionFound) { - size_t equalsPos = line.find('='); - if (equalsPos != std::string::npos) { - std::string keyInFile = line.substr(0, equalsPos); - trimInPlace(keyInFile); - if (keyInFile == desiredKey) { - continue; - } + if (!line.empty()) { + if (line[0] == '[' && line.back() == ']') { + currentSection = line.substr(1, line.length() - 2); + sectionFound = (currentSection == desiredSection); + } else if (sectionFound) { + size_t equalsPos = line.find('='); + if (equalsPos != std::string::npos) { + std::string keyInFile = line.substr(0, equalsPos); + trimInPlace(keyInFile); + if (keyInFile == desiredKey) { + continue; + } + } + } + newLines.push_back(line); } - } - newLines.push_back(line); } - } - file.close(); - std::ofstream outfile(fileToEdit); - for (const auto& line : newLines) { - outfile << line << std::endl; - } - outfile.close(); + file.close(); + std::ofstream outfile(fileToEdit); + for (const auto& line : newLines) { + outfile << line << std::endl; + } + outfile.close(); - return true; + return true; } -std::string readIniValue(const std::string& filePath, const std::string& section, const std::string& key) { +std::string readIniValue(const std::string& filePath, const std::string& section, const std::string& key) +{ std::ifstream file(filePath); std::string line, currentSection; bool sectionFound = false; @@ -587,7 +593,8 @@ std::string readIniValue(const std::string& filePath, const std::string& section return ""; // Key not found } -std::vector> parseIntIniData (std::string input, bool skipFirstItem = true) { +std::vector> parseIntIniData(std::string input, bool skipFirstItem = true) +{ // Remove outer brackets input = input.substr(6, input.length() - 3); @@ -603,7 +610,7 @@ std::vector> parseIntIniData (std::string input, bool skipFirst if (openBracket == '[') { std::vector array(4); ss >> array[0] >> comma1 >> array[1] >> comma2 >> array[2] >> comma1 >> array[3] >> closeBracket; - + // Check if it's not the first item and then add to the result if (!skipFirstItem) { result.push_back(array); @@ -615,15 +622,14 @@ std::vector> parseIntIniData (std::string input, bool skipFirst } } - return result; } - -bool isLineExistInIni(const std::string& filename, std::string& lineToFind) { +bool isLineExistInIni(const std::string& filename, std::string& lineToFind) +{ std::ifstream infile(filename); std::string line; - + if (!infile) { log("isLineExistInIni: Failed to open file: %s", filename.c_str()); return false; @@ -633,8 +639,8 @@ bool isLineExistInIni(const std::string& filename, std::string& lineToFind) { while (std::getline(infile, line)) { if (std::regex_match(line, pattern)) { - infile.close(); - return true; + infile.close(); + return true; } } diff --git a/source/json_funcs.hpp b/source/json_funcs.hpp index bd00a956..7c04953d 100644 --- a/source/json_funcs.hpp +++ b/source/json_funcs.hpp @@ -1,24 +1,43 @@ #pragma once +#include +#include + #include #include -#include -#include class SafeJson { public: - SafeJson(json_t* json) : _json(json) {} - SafeJson(const SafeJson& rh) : _json(rh._json) { json_incref(_json); }; - SafeJson(SafeJson&& rh) : _json(rh._json) { rh._json = nullptr; } - ~SafeJson() { if (_json) { json_decref(_json); } } - operator json_t* () { return _json; } + SafeJson(json_t* json) + : _json(json) + { + } + SafeJson(const SafeJson& rh) + : _json(rh._json) + { + json_incref(_json); + }; + SafeJson(SafeJson&& rh) + : _json(rh._json) + { + rh._json = nullptr; + } + ~SafeJson() + { + if (_json) { + json_decref(_json); + } + } + operator json_t*() { return _json; } operator bool() { return nullptr != _json; } auto operator->() { return _json; } + private: - json_t* _json{ nullptr }; + json_t* _json { nullptr }; }; -SafeJson readJsonFromFile(const std::string& filePath) { +SafeJson readJsonFromFile(const std::string& filePath) +{ // Check if the file exists struct stat fileStat; if (stat(filePath.c_str(), &fileStat) != 0) { diff --git a/source/main.cpp b/source/main.cpp index d4ccad92..b443fa37 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -1,18 +1,19 @@ #define NDEBUG #define STBTT_STATIC #define TESLA_INIT_IMPL -#include + #include -#include #include -#include +#include #include +#include +#include // Overlay booleans static bool defaultMenuLoaded = true; static std::string package = ""; bool enableConfigNav = false; -bool showCurInMenu = false; +bool showCurInMenu = false; std::string kipVersion = ""; bool DownloadProcessing = false; bool sameKeyCombo = false; @@ -36,10 +37,15 @@ class ConfigOverlay : public tsl::Gui { bool isInSection, inQuotes; public: - ConfigOverlay(const std::string& file, const std::string& key = "") : filePath(file), specificKey(key) {} - ~ConfigOverlay() {} + ConfigOverlay(const std::string& file, const std::string& key = "") + : filePath(file) + , specificKey(key) + { + } + ~ConfigOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("ConfigOverlay"); auto rootFrame = new tsl::elm::OverlayFrame(getNameFromPath(filePath), "Uberhand Config"); auto list = new tsl::elm::List(); @@ -125,13 +131,14 @@ class ConfigOverlay : public tsl::Gui { bool adjuct_top, adjuct_bot = false; - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (this->adjuct_top) { // Adjust cursor to the top item after jump bot-top this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -142,7 +149,7 @@ class ConfigOverlay : public tsl::Gui { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -167,7 +174,8 @@ class ConfigOverlay : public tsl::Gui { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -195,11 +203,17 @@ class SelectionOverlay : public tsl::Gui { tsl::elm::ListItem* savedItem = nullptr; public: - SelectionOverlay(const std::string& file, const std::string& key = "", const std::vector>& cmds = {}, std::string footer = "") - : filePath(file), specificKey(key), footer(footer), commands(cmds) {} - ~SelectionOverlay() {} + SelectionOverlay(const std::string& file, const std::string& key = "", const std::vector>& cmds = {}, std::string footer = "") + : filePath(file) + , specificKey(key) + , footer(footer) + , commands(cmds) + { + } + ~SelectionOverlay() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("SelectionOverlay"); bool hasHelp = false; @@ -217,7 +231,7 @@ class SelectionOverlay : public tsl::Gui { helpPath += "/Help/" + getNameFromPath(filePath) + ".txt"; } if (isFileOrDirectory(helpPath)) { - hasHelp = true; + hasHelp = true; } else { helpPath = ""; } @@ -242,9 +256,9 @@ class SelectionOverlay : public tsl::Gui { std::string offset = ""; std::pair textDataPair; - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int fontSize = 19; // Adjust the font size as needed - + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int fontSize = 19; // Adjust the font size as needed + for (const auto& cmd : commands) { if (cmd.size() > 1) { if (cmd[0] == "split") { @@ -295,26 +309,27 @@ class SelectionOverlay : public tsl::Gui { } useJson = true; if (cmd.size() > 5) { // Enough parts are provided to mark the current ini value - sourceIni = preprocessPath(cmd[3]); + sourceIni = preprocessPath(cmd[3]); sectionIni = cmd[4]; - keyIni = cmd[5]; + keyIni = cmd[5]; markCurIni = true; } } else if (cmd[0] == "text_source") { textPath = preprocessPath(cmd[1]); useText = true; } - } + } } // Get the list of files matching the pattern - + if (!useToggle) { if (useText) { if (!isFileOrDirectory(textPath)) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("Text file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("Text file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize + lineHeight); rootFrame->setContent(list); return rootFrame; } else { @@ -322,25 +337,27 @@ class SelectionOverlay : public tsl::Gui { std::string textdata = textDataPair.first; int textsize = textDataPair.second; if (!textdata.empty()) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * textsize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize, textdata](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(textdata.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * textsize + lineHeight); rootFrame->setContent(list); return rootFrame; } } } else if (useJson) { if (!isFileOrDirectory(jsonPath)) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("JSON file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("JSON file not found.\nContact the package dev.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize + lineHeight); rootFrame->setContent(list); return rootFrame; } else { std::string currentHex = ""; // Is used to mark current value from the kip bool detectSize = true; searchCurrent = markCurKip || markCurIni ? true : false; - // create list of data in the json + // create list of data in the json auto jsonData = readJsonFromFile(jsonPath); if (jsonData && json_is_array(jsonData)) { size_t arraySize = json_array_size(jsonData); @@ -375,25 +392,23 @@ class SelectionOverlay : public tsl::Gui { if (decValue) { currentHex = std::to_string(reversedHexToInt(currentHex)); } - } - catch (const std::invalid_argument& ex) { + } catch (const std::invalid_argument& ex) { log("ERROR - %s:%d - invalid offset value: \"%s\" in \"%s\"", __func__, __LINE__, offset.c_str(), jsonPath.c_str()); } } if (valueStr == currentHex) { name = json_string_value(keyValue); if (name.find(" - ") != std::string::npos) { - name = name + " | " + checkmarkChar; - } else { - name = name + " - " + checkmarkChar; + name = name + " | " + checkmarkChar; + } else { + name = name + " - " + checkmarkChar; } searchCurrent = false; - } - else { + } else { name = json_string_value(keyValue); } } else if (markCurIni && hexOrDecOrVal && searchCurrent) { - const char* iniValueStr; + const char* iniValueStr; if (hexValue) { iniValueStr = json_string_value(hexValue); } else if (decValue) { @@ -405,17 +420,16 @@ class SelectionOverlay : public tsl::Gui { if (iniValueStr == iniValue) { name = json_string_value(keyValue); if (name.find(" - ") != std::string::npos) { - name = name + " | " + checkmarkChar; - } else { - name = name + " - " + checkmarkChar; + name = name + " | " + checkmarkChar; + } else { + name = name + " - " + checkmarkChar; } searchCurrent = false; - } - else { + } else { name = json_string_value(keyValue); } } else { - name = json_string_value(keyValue); + name = json_string_value(keyValue); } if (colorValue) { name = name + " ::" + json_string_value(colorValue); @@ -435,7 +449,7 @@ class SelectionOverlay : public tsl::Gui { } else { filesListOn = getFilesListByWildcards(pathPatternOn); filesListOff = getFilesListByWildcards(pathPatternOff); - + // Apply On Filter for (const auto& filterOnPath : filterOnList) { removeEntryFromList(filterOnPath, filesListOn); @@ -444,12 +458,10 @@ class SelectionOverlay : public tsl::Gui { for (const auto& filterOnPath : filterOffList) { removeEntryFromList(filterOnPath, filesListOff); } - - + // remove filterOnPath from filesListOn // remove filterOffPath from filesListOff - - + filesList.reserve(filesListOn.size() + filesListOff.size()); filesList.insert(filesList.end(), filesListOn.begin(), filesListOn.end()); filesList.insert(filesList.end(), filesListOff.begin(), filesListOff.end()); @@ -457,7 +469,7 @@ class SelectionOverlay : public tsl::Gui { std::sort(filesList.begin(), filesList.end(), [](const std::string& a, const std::string& b) { std::string parentDirA = getParentDirNameFromPath(a); std::string parentDirB = getParentDirNameFromPath(b); - + // Compare parent directory names if (parentDirA != parentDirB) { return parentDirA < parentDirB; @@ -465,7 +477,7 @@ class SelectionOverlay : public tsl::Gui { // Parent directory names are the same, compare filenames std::string filenameA = getNameFromPath(a); std::string filenameB = getNameFromPath(b); - + // Compare filenames return filenameA < filenameB; } @@ -475,15 +487,13 @@ class SelectionOverlay : public tsl::Gui { return getNameFromPath(a) < getNameFromPath(b); }); } - - } - + // Apply filter for (const auto& filterPath : filterList) { removeEntryFromList(filterPath, filesList); } - + // Add each file as a menu item int count = 0; std::string jsonSep = ""; @@ -496,7 +506,7 @@ class SelectionOverlay : public tsl::Gui { itemName = dropExtension(itemName); } parentDirName = getParentDirNameFromPath(file); - if (useSplitHeader && (lastParentDirName.empty() || (lastParentDirName != parentDirName))){ + if (useSplitHeader && (lastParentDirName.empty() || (lastParentDirName != parentDirName))) { list->addItem(new tsl::elm::CategoryHeader(removeQuotes(parentDirName))); lastParentDirName = parentDirName; } @@ -521,13 +531,11 @@ class SelectionOverlay : public tsl::Gui { if (isFirst) { jsonSep = optionName.substr(1); hasSep = true; - } - else { + } else { auto item = new tsl::elm::CategoryHeader(optionName.substr(1), true); list->addItem(item); } - } - else { + } else { isFirst = false; auto listItem = new tsl::elm::ListItem(optionName); if (ramInfo) { @@ -575,10 +583,10 @@ class SelectionOverlay : public tsl::Gui { } return false; }); - if (color.compare(0, 1, "#") == 0){ + if (color.compare(0, 1, "#") == 0) { listItem->setColor(tsl::PredefinedColors::Custom, color); } else { - listItem->setColor(defineColor(color)); + listItem->setColor(defineColor(color)); } // Find the curent list item to jump to size_t checkmarkPos = listItem->getValue().find(checkmarkChar); @@ -604,7 +612,7 @@ class SelectionOverlay : public tsl::Gui { std::string concatenatedString; // Iterate through the vector and append each string with a space - for (auto & str : kipInfoCommand) { + for (auto& str : kipInfoCommand) { if (str == "{source}") { str = replacePlaceholder(str, "{source}", file); } @@ -682,14 +690,14 @@ class SelectionOverlay : public tsl::Gui { } }); list->addItem(toggleListItem); - } + } count++; } if (hasSep) { if (!jsonSep.empty()) { list->addItem(new tsl::elm::CategoryHeader(jsonSep), 0, 0); } - } else if (!useSplitHeader){ + } else if (!useSplitHeader) { list->addItem(new tsl::elm::CategoryHeader(specificKey), 0, 0); } rootFrame->setContent(list); @@ -698,11 +706,12 @@ class SelectionOverlay : public tsl::Gui { bool adjuct_top, adjuct_bot = false; - virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(u64 keysDown, u64 keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (!keysDown) { if (this->savedItem != nullptr && this->savedItem != this->getFocusedElement()) { - while(this->savedItem != this->getFocusedElement()) { - this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); + while (this->savedItem != this->getFocusedElement()) { + this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); } } else { this->savedItem = nullptr; @@ -723,7 +732,7 @@ class SelectionOverlay : public tsl::Gui { this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -734,7 +743,7 @@ class SelectionOverlay : public tsl::Gui { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -759,7 +768,8 @@ class SelectionOverlay : public tsl::Gui { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -780,8 +790,7 @@ class SelectionOverlay : public tsl::Gui { if (applied) { resetValue = true; focusedItem->setValue("APPLIED", tsl::PredefinedColors::Green); - } - else + } else focusedItem->setValue("DELETED", tsl::PredefinedColors::Red); applied = false; deleted = false; @@ -791,14 +800,16 @@ class SelectionOverlay : public tsl::Gui { } }; - class SubMenu : public tsl::Gui { protected: std::string subPath, pathReplace, pathReplaceOn, pathReplaceOff; public: - SubMenu(const std::string& path) : subPath(path) {} - ~SubMenu() {} + SubMenu(const std::string& path) + : subPath(path) + { + } + ~SubMenu() { } FILE* kipFile = nullptr; int custOffset; @@ -806,7 +817,7 @@ class SubMenu : public tsl::Gui { auto addSliderItem(auto& sliderOption) { const std::string& sliderName = sliderOption[1]; - const int low = std::stoi(sliderOption[2]); + const int low = std::stoi(sliderOption[2]); const int high = std::stoi(sliderOption[3]); const int step = std::stoi(sliderOption[4]); const std::string& offset = sliderOption[5]; @@ -820,11 +831,11 @@ class SubMenu : public tsl::Gui { } myArray.shrink_to_fit(); - auto slider = new tsl::elm::NamedStepTrackBar(" ",myArray); + auto slider = new tsl::elm::NamedStepTrackBar(" ", myArray); std::string currentHex = readHexDataAtOffset("/atmosphere/kips/loader.kip", CUST, std::stoul(offset), 4); - int initProgress = (reversedHexToInt(currentHex) - low)/step; + int initProgress = (reversedHexToInt(currentHex) - low) / step; slider->setProgress(initProgress); @@ -835,7 +846,7 @@ class SubMenu : public tsl::Gui { hexEditCustOffset("/atmosphere/kips/loader.kip", std::stoul(offset), hexData); slider->setColor(tsl::PredefinedColors::Green); return true; - } else if (keys){ + } else if (keys) { slider->setColor(); } return false; @@ -843,7 +854,8 @@ class SubMenu : public tsl::Gui { return slider; } - std::string findCurrentKip(const std::string& jsonPath, const std::string& offset) { + std::string findCurrentKip(const std::string& jsonPath, const std::string& offset) + { std::string searchKey; const char* valueStr; @@ -863,13 +875,11 @@ class SubMenu : public tsl::Gui { searchKey = "hex"; hexLength = strlen(valueStr) / 2; hexLength = std::max(hexLength, 1); - } - else if ((decValue && json_is_string(decValue))) { + } else if ((decValue && json_is_string(decValue))) { valueStr = json_string_value(decValue); searchKey = "dec"; hexLength = 4; - } - else { + } else { return "\u25B6"; } std::string currentHex; @@ -880,8 +890,7 @@ class SubMenu : public tsl::Gui { custOffset = findCustOffset(kipFile); } currentHex = readHexDataAtOffset(kipFile, CUST, std::stoul(offset), hexLength, custOffset); - } - catch (const std::invalid_argument& ex) { + } catch (const std::invalid_argument& ex) { log("ERROR - %s:%d - invalid offset value: \"%s\" in \"%s\"", __func__, __LINE__, offset.c_str(), jsonPath.c_str()); } if (!currentHex.empty()) { @@ -911,7 +920,8 @@ class SubMenu : public tsl::Gui { return "\u25B6"; } - std::string findCurrentIni(const std::string& jsonPath, const std::string& iniPath, const std::string& section, const std::string& key) { + std::string findCurrentIni(const std::string& jsonPath, const std::string& iniPath, const std::string& section, const std::string& key) + { std::string searchKey; auto jsonData = readJsonFromFile(jsonPath); @@ -927,14 +937,11 @@ class SubMenu : public tsl::Gui { json_t* otherValue = json_object_get(item, "value"); if ((hexValue && json_is_string(hexValue))) { searchKey = "hex"; - } - else if ((decValue && json_is_string(decValue))) { + } else if ((decValue && json_is_string(decValue))) { searchKey = "dec"; - } - else if ((otherValue && json_is_string(otherValue))) { + } else if ((otherValue && json_is_string(otherValue))) { searchKey = "value"; - } - else { + } else { return "\u25B6"; } std::string iniValue = readIniValue(iniPath, section, key); @@ -962,7 +969,8 @@ class SubMenu : public tsl::Gui { return "\u25B6"; } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("SubMenu"); int numSlashes = count(subPath.begin(), subPath.end(), '/'); @@ -975,7 +983,7 @@ class SubMenu : public tsl::Gui { helpPath = subPath.substr(0, fifthSlashPos); helpPath += "/Help/" + getNameFromPath(subPath) + ".txt"; if (isFileOrDirectory(helpPath)) { - hasHelp = true; + hasHelp = true; } else { helpPath = ""; } @@ -984,19 +992,20 @@ class SubMenu : public tsl::Gui { std::string viewPackage = package; std::string viewsubPath = getNameFromPath(subPath); - auto rootFrame = new tsl::elm::OverlayFrame(getNameFromPath(viewsubPath), viewPackage, "" , hasHelp); + auto rootFrame = new tsl::elm::OverlayFrame(getNameFromPath(viewsubPath), viewPackage, "", hasHelp); auto list = new tsl::elm::List(); if (!kipVersion.empty()) { - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int fontSize = 19; // Adjust the font size as needed + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int fontSize = 19; // Adjust the font size as needed const std::string CUST = "43555354"; std::string curKipVer = readHexDataAtOffset("/atmosphere/kips/loader.kip", CUST, 4, 3); int i_curKipVer = reversedHexToInt(curKipVer); if (std::stoi(kipVersion) != i_curKipVer) { - list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString("Kip version mismatch.\nUpdate the requirements to use this\npackage.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * 3 + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, fontSize](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("Kip version mismatch.\nUpdate the requirements to use this\npackage.", false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * 3 + lineHeight); rootFrame->setContent(list); return rootFrame; } @@ -1009,7 +1018,7 @@ class SubMenu : public tsl::Gui { if (isFileOrDirectory(subPath + subDirectory + '/' + configFileName)) { auto item = new tsl::elm::ListItem(subDirectory); item->setValue("\u25B6", tsl::PredefinedColors::White); - item->setClickListener([&, subDirectory, helpPath](u64 keys)->bool { + item->setClickListener([&, subDirectory, helpPath](u64 keys) -> bool { if (keys & KEY_A) { tsl::changeTo(subPath + subDirectory + '/'); return true; @@ -1018,7 +1027,7 @@ class SubMenu : public tsl::Gui { return true; } return false; - }); + }); list->addItem(item); } } @@ -1033,14 +1042,14 @@ class SubMenu : public tsl::Gui { // Package Info PackageHeader packageHeader = getPackageHeaderFromIni(subConfigIniPath); - + // Populate the sub menu with options for (const auto& option : options) { std::string optionName = option.first; - std::string footer; + std::string footer; bool usePattern = false; - bool useSlider = false; - bool useSliderItem = false; + bool useSlider = false; + bool useSliderItem = false; std::string toggleMode; std::string toggleVerPath; std::string toggleVerLine; @@ -1049,7 +1058,7 @@ class SubMenu : public tsl::Gui { std::vector tmpldir = option.second[0]; auto item = new tsl::elm::ListItem(optionName.substr(1)); item->setValue("\u25B6", tsl::PredefinedColors::White); - item->setClickListener([&, tmpldir, item](u64 keys)->bool { + item->setClickListener([&, tmpldir, item](u64 keys) -> bool { if (keys & KEY_A) { if (!isFileOrDirectory(tmpldir[1])) { item->setValue("FAIL", tsl::PredefinedColors::Red); @@ -1059,7 +1068,7 @@ class SubMenu : public tsl::Gui { return true; } return false; - }); + }); list->addItem(item); continue; } @@ -1067,7 +1076,7 @@ class SubMenu : public tsl::Gui { auto subDirectory = optionName.substr(1); auto item = new tsl::elm::ListItem(subDirectory); item->setValue("\u25B6", tsl::PredefinedColors::White); - item->setClickListener([&, subDirectory, item, helpPath](u64 keys)->bool { + item->setClickListener([&, subDirectory, item, helpPath](u64 keys) -> bool { if (keys & KEY_A) { if (!isDirectory(subPath + subDirectory + '/')) { item->setValue("FAIL", tsl::PredefinedColors::Red); @@ -1080,11 +1089,10 @@ class SubMenu : public tsl::Gui { return true; } return false; - }); + }); list->addItem(item); continue; - } - else if (optionName[0] == '*') { + } else if (optionName[0] == '*') { if (option.second[0][0] == "slider_kip") { useSliderItem = true; footer = ""; @@ -1106,7 +1114,7 @@ class SubMenu : public tsl::Gui { } size_t pos = optionName.find(" ;; "); // Find the custom display header - if (pos!= std::string::npos) { + if (pos != std::string::npos) { headerName = optionName.substr(pos + 4); // Strip the item name optionName.resize(pos); // Strip the displayName } else { @@ -1118,7 +1126,7 @@ class SubMenu : public tsl::Gui { bool useAdvToggle = false; bool isSeparator = false; for (const auto& cmd : option.second) { - if(cmd[0] == "separator"){ + if (cmd[0] == "separator") { isSeparator = true; break; } @@ -1139,7 +1147,7 @@ class SubMenu : public tsl::Gui { } useAdvToggle = true; } - } + } } if (isSeparator) { @@ -1192,21 +1200,21 @@ class SubMenu : public tsl::Gui { listItem->setValue(findCurrentKip(jsonPath, offset)); } if ((cmd[0] == "json_mark_cur_ini") && showCurInMenu) { - std::string sourceIni = preprocessPath(cmd[3]); + std::string sourceIni = preprocessPath(cmd[3]); auto& sectionIni = cmd[4]; - auto& keyIni = cmd[5]; - std::string jsonPath = preprocessPath(cmd[1]); + auto& keyIni = cmd[5]; + std::string jsonPath = preprocessPath(cmd[1]); listItem->setValue(findCurrentIni(jsonPath, sourceIni, sectionIni, keyIni)); } } - + listItem->setClickListener([command = option.second, keyName = headerName, subPath = this->subPath, usePattern, listItem, helpPath, useSlider](uint64_t keys) { - if (exitMT){ + if (exitMT) { // Means that commands was executed threadClose(&threadMT); exitMT = false; Mtrun = false; - + if (errCode == 1) { tsl::goBack(); return true; @@ -1249,9 +1257,9 @@ class SubMenu : public tsl::Gui { } else if (keys && (listItem->getValue() == "DONE" || listItem->getValue() == "FAIL")) { listItem->setValue(""); } - return false; - } - return false; + return false; + } + return false; }); list->addItem(listItem); @@ -1259,7 +1267,7 @@ class SubMenu : public tsl::Gui { auto toggleListItem = new tsl::elm::ToggleListItem(optionName, false, "On", "Off"); // Set the initial state of the toggle item bool toggleStateOn = isFileOrDirectory(preprocessPath(pathReplaceOn)); - + toggleListItem->setState(toggleStateOn); toggleListItem->setStateChangedListener([toggleStateOn, command = option.second, this](bool state) { @@ -1286,46 +1294,45 @@ class SubMenu : public tsl::Gui { list->addItem(toggleListItem); } - } if (kipFile) { fclose(kipFile); kipFile = nullptr; } - constexpr int lineHeight = 20; // Adjust the line height as needed - constexpr int xOffset = 120; // Adjust the horizontal offset as needed - constexpr int fontSize = 16; // Adjust the font size as needed - int numEntries = 0; // Adjust the number of entries as needed - + constexpr int lineHeight = 20; // Adjust the line height as needed + constexpr int xOffset = 120; // Adjust the horizontal offset as needed + constexpr int fontSize = 16; // Adjust the font size as needed + int numEntries = 0; // Adjust the number of entries as needed + std::string packageSectionString = ""; std::string packageInfoString = ""; if (packageHeader.version != "") { packageSectionString += "Version\n"; - packageInfoString += (packageHeader.version+"\n").c_str(); + packageInfoString += (packageHeader.version + "\n").c_str(); numEntries++; } if (packageHeader.creator != "") { packageSectionString += "Creator(s)\n"; - packageInfoString += (packageHeader.creator+"\n").c_str(); + packageInfoString += (packageHeader.creator + "\n").c_str(); numEntries++; } if (packageHeader.about != "") { std::string aboutHeaderText = "About\n"; std::string::size_type aboutHeaderLength = aboutHeaderText.length(); std::string aboutText = packageHeader.about; - + packageSectionString += aboutHeaderText; - + // Split the about text into multiple lines with proper word wrapping - constexpr int maxLineLength = 28; // Adjust the maximum line length as needed + constexpr int maxLineLength = 28; // Adjust the maximum line length as needed std::string::size_type startPos = 0; std::string::size_type spacePos = 0; - + while (startPos < aboutText.length()) { std::string::size_type endPos = std::min(startPos + maxLineLength, aboutText.length()); std::string line = aboutText.substr(startPos, endPos - startPos); - + // Check if the current line ends with a space; if not, find the last space in the line if (endPos < aboutText.length() && aboutText[endPos] != ' ') { spacePos = line.find_last_of(' '); @@ -1334,20 +1341,18 @@ class SubMenu : public tsl::Gui { line = aboutText.substr(startPos, endPos - startPos); } } - + packageInfoString += line + '\n'; startPos = endPos + 1; numEntries++; - + // Add corresponding newline to the packageSectionString if (startPos < aboutText.length()) { packageSectionString += std::string(aboutHeaderLength, ' ') + '\n'; } } - } - // Remove trailing newline character if ((packageSectionString != "") && (packageSectionString.back() == '\n')) { packageSectionString.resize(packageSectionString.size() - 1); @@ -1355,18 +1360,18 @@ class SubMenu : public tsl::Gui { if ((packageInfoString != "") && (packageInfoString.back() == '\n')) { packageInfoString.resize(packageInfoString.size() - 1); } - - + if ((packageSectionString != "") && (packageInfoString != "")) { list->addItem(new tsl::elm::CategoryHeader("Package Info")); - list->addItem(new tsl::elm::CustomDrawer([lineHeight, xOffset, fontSize, packageSectionString, packageInfoString](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(packageSectionString.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - renderer->drawString(packageInfoString.c_str(), false, x + xOffset, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * numEntries + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, xOffset, fontSize, packageSectionString, packageInfoString](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(packageSectionString.c_str(), false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + renderer->drawString(packageInfoString.c_str(), false, x + xOffset, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * numEntries + lineHeight); } if (numSlashes == 5 && integrityCheck) { - int headerCh[] = {83, 112, 101, 99, 105, 97, 108, 32, 84, 104, 97, 110, 107, 115}; + int headerCh[] = { 83, 112, 101, 99, 105, 97, 108, 32, 84, 104, 97, 110, 107, 115 }; int length = sizeof(headerCh) / sizeof(headerCh[0]); char* charArray = new char[length + 1]; for (int i = 0; i < length; ++i) { @@ -1374,26 +1379,28 @@ class SubMenu : public tsl::Gui { } charArray[length] = '\0'; list->addItem(new tsl::elm::CategoryHeader(charArray)); - int checksum[] = {83, 112, 101, 99, 105, 97, 108, 32, 116, 104, 97, 110, 107, 115, 32, 116, 111, 32, 69, 102, 111, 115, 97, 109, 97, 114, 107, 44, 32, 73, 114, 110, 101, 32, 97, 110, 100, 32, 73, 51, 115, 101, 121, 46, 10, 87, 105, 116, 104, 111, 117, 116, 32, 116, 104, 101, 109, 32, 116, 104, 105, 115, 32, 119, 111, 117, 108, 100, 110, 39, 116, 32, 98, 101, 32, 112, 111, 115, 115, 98, 108, 101, 33}; + int checksum[] = { 83, 112, 101, 99, 105, 97, 108, 32, 116, 104, 97, 110, 107, 115, 32, 116, 111, 32, 69, 102, 111, 115, 97, 109, 97, 114, 107, 44, 32, 73, 114, 110, 101, 32, 97, 110, 100, 32, 73, 51, 115, 101, 121, 46, 10, 87, 105, 116, 104, 111, 117, 116, 32, 116, 104, 101, 109, 32, 116, 104, 105, 115, 32, 119, 111, 117, 108, 100, 110, 39, 116, 32, 98, 101, 32, 112, 111, 115, 115, 98, 108, 101, 33 }; length = sizeof(checksum) / sizeof(checksum[0]); charArray = new char[length + 1]; for (int i = 0; i < length; ++i) { charArray[i] = static_cast(checksum[i]); } charArray[length] = '\0'; - list->addItem(new tsl::elm::CustomDrawer([lineHeight, xOffset, fontSize, charArray](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(charArray, false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); - }), fontSize * 2 + lineHeight); + list->addItem(new tsl::elm::CustomDrawer([lineHeight, xOffset, fontSize, charArray](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString(charArray, false, x, y + lineHeight, fontSize, a(tsl::style::color::ColorText)); + }), + fontSize * 2 + lineHeight); } rootFrame->setContent(list); - + return rootFrame; } bool adjuct_top, adjuct_bot = false; - virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (resetValue && keysDown) { if (this->getFocusedElement()->getClass() == tsl::Class::ListItem) { tsl::elm::ListItem* focusedItem = dynamic_cast(this->getFocusedElement()); @@ -1409,7 +1416,7 @@ class SubMenu : public tsl::Gui { this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -1420,7 +1427,7 @@ class SubMenu : public tsl::Gui { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -1445,7 +1452,8 @@ class SubMenu : public tsl::Gui { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -1461,7 +1469,7 @@ class SubMenu : public tsl::Gui { } else if (applied && !keysDown) { applied = false; resetValue = true; - tsl::elm::ListItem* focusedItem = dynamic_cast(this-> getFocusedElement()); + tsl::elm::ListItem* focusedItem = dynamic_cast(this->getFocusedElement()); if (prevValue.empty()) prevValue = focusedItem->getValue(); focusedItem->setValue("APPLIED", tsl::PredefinedColors::Green); @@ -1475,9 +1483,13 @@ class MainMenu; class Package : public SubMenu { public: - Package(const std::string& path) : SubMenu(path) {} + Package(const std::string& path) + : SubMenu(path) + { + } - tsl::elm::Element* createUI() override { + tsl::elm::Element* createUI() override + { package = getNameFromPath(subPath); std::string subConfigIniPath = subPath + "/" + configFileName; PackageHeader packageHeader = getPackageHeaderFromIni(subConfigIniPath); @@ -1493,13 +1505,14 @@ class Package : public SubMenu { bool adjuct_top, adjuct_bot = false; - bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (this->adjuct_top) { // Adjust cursor to the top item after jump bot-top this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -1510,7 +1523,7 @@ class Package : public SubMenu { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -1535,7 +1548,8 @@ class Package : public SubMenu { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -1557,9 +1571,14 @@ class Updater : public tsl::Gui { Screen prevMenu; public: - Updater(const std::vector>& items, Screen mode = Overlays) : uitems(items), prevMenu(mode) {} + Updater(const std::vector>& items, Screen mode = Overlays) + : uitems(items) + , prevMenu(mode) + { + } - tsl::elm::Element* createUI() override { + tsl::elm::Element* createUI() override + { auto rootFrame = new tsl::elm::OverlayFrame("Updates available", "Updater"); auto list = new tsl::elm::List(); @@ -1648,13 +1667,14 @@ class Updater : public tsl::Gui { bool adjuct_top, adjuct_bot = false; - bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (this->adjuct_top) { // Adjust cursor to the top item after jump bot-top this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -1665,7 +1685,7 @@ class Updater : public tsl::Gui { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -1690,7 +1710,8 @@ class Updater : public tsl::Gui { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -1707,7 +1728,6 @@ class Updater : public tsl::Gui { } }; - class MainMenu : public tsl::Gui { private: tsl::hlp::ini::IniData settingsData; @@ -1720,40 +1740,45 @@ class MainMenu : public tsl::Gui { bool overlayUpdater = true; bool sorting = false; Screen ForMode; + public: - MainMenu(const Screen& curScreen=Default) : ForMode(curScreen){} - ~MainMenu() {} + MainMenu(const Screen& curScreen = Default) + : ForMode(curScreen) + { + } + ~MainMenu() { } - virtual tsl::elm::Element* createUI() override { + virtual tsl::elm::Element* createUI() override + { // log ("MainMenu"); defaultMenuMode = "overlays"; menuMode = "overlays"; - + createDirectory(packageDirectory); createDirectory(settingsPath); switch (ForMode) { - case Soverlays: - sorting = true; - menuMode = "overlays"; - break; - case Spackages: - sorting = true; - menuMode = "packages"; - break; - case Overlays: - sorting = false; - menuMode = "overlays"; - break; - case Packages: - sorting = false; - menuMode = "packages"; - break; - case Default: - break; - } - + case Soverlays: + sorting = true; + menuMode = "overlays"; + break; + case Spackages: + sorting = true; + menuMode = "packages"; + break; + case Overlays: + sorting = false; + menuMode = "overlays"; + break; + case Packages: + sorting = false; + menuMode = "packages"; + break; + case Default: + break; + } + bool settingsLoaded = false; if (isFileOrDirectory(settingsConfigIniPath)) { settingsData = getParsedDataFromIniFile(settingsConfigIniPath); @@ -1778,12 +1803,12 @@ class MainMenu : public tsl::Gui { } else { setIniFileValue(settingsConfigIniPath, "uberhand", "show_pack_versions", "false"); } - if (uberhandSection["uberhand_updates_only"] == "true"){ + if (uberhandSection["uberhand_updates_only"] == "true") { uberhand_updates_only = true; } else { setIniFileValue(settingsConfigIniPath, "uberhand", "uberhand_updates_only", "false"); } - if (!uberhandSection["ovl_repo"].empty()){ + if (!uberhandSection["ovl_repo"].empty()) { repoUrl = uberhandSection["ovl_repo"]; } else { repoUrl = "https://raw.githubusercontent.com/i3sey/uUpdater-ovl-repo/main/main.ini"; @@ -1802,8 +1827,7 @@ class MainMenu : public tsl::Gui { if (!(uberhandSection["show_separator"] == "true")) { setIniFileValue(settingsConfigIniPath, "uberhand", "show_separator", "false"); } - if (uberhandSection["key_combo"].empty()) - { + if (uberhandSection["key_combo"].empty()) { copyTeslaKeyComboTouberhand(); } else { if (!isDirectory("sdmc:/config/tesla/")) { @@ -1821,17 +1845,16 @@ class MainMenu : public tsl::Gui { } } } - + if (!isFileOrDirectory("sdmc:/config/tesla/config.ini")) // Create and modify tesla kinfog - if (!settingsLoaded) { // write data if settings are not loaded - setIniFileValue(settingsConfigIniPath, "uberhand", "default_menu", defaultMenuMode); - setIniFileValue(settingsConfigIniPath, "uberhand", "last_menu", menuMode); - setIniFileValue(settingsConfigIniPath, "uberhand", "in_overlay", "false"); - } + if (!settingsLoaded) { // write data if settings are not loaded + setIniFileValue(settingsConfigIniPath, "uberhand", "default_menu", defaultMenuMode); + setIniFileValue(settingsConfigIniPath, "uberhand", "last_menu", menuMode); + setIniFileValue(settingsConfigIniPath, "uberhand", "in_overlay", "false"); + } //setIniFileValue(settingsConfigIniPath, "uberhand", "in_overlay", "false"); - - + if ((defaultMenuMode == "overlays") || (defaultMenuMode == "packages")) { if (defaultMenuLoaded) { menuMode = defaultMenuMode; @@ -1841,18 +1864,18 @@ class MainMenu : public tsl::Gui { defaultMenuMode = "last_menu"; setIniFileValue(settingsConfigIniPath, "uberhand", "default_menu", defaultMenuMode); } - - std::string versionLabel = APP_VERSION+std::string(" (")+envGetLoaderInfo()+std::string(")"); + + std::string versionLabel = APP_VERSION + std::string(" (") + envGetLoaderInfo() + std::string(")"); auto rootFrame = new tsl::elm::OverlayFrame("Uberhand", versionLabel, menuMode); auto list = new tsl::elm::List(); //loadOverlayFiles(list); int count = 0; - + if (menuMode == "overlays") { // Load overlay files - std::vector overlayFiles = getFilesListByWildcard(overlayDirectory+"*.ovl"); + std::vector overlayFiles = getFilesListByWildcard(overlayDirectory + "*.ovl"); FILE* overlaysIniFile = fopen(overlaysIniFilePath.c_str(), "r"); if (!overlaysIniFile) { @@ -1869,18 +1892,18 @@ class MainMenu : public tsl::Gui { std::multimap order; std::map alpSort; - for (const std::string& sortElem : overlayFiles){ + for (const std::string& sortElem : overlayFiles) { auto [result, overlayName, overlayVersion] = getOverlayInfo(sortElem); - if (result != ResultSuccess){ + if (result != ResultSuccess) { continue; } - if (overlayName == "Uberhand"){ + if (overlayName == "Uberhand") { continue; } alpSort[overlayName] = sortElem; } overlayFiles.clear(); - for (const auto & overlay : alpSort) { + for (const auto& overlay : alpSort) { overlayFiles.push_back(overlay.second); } @@ -1888,7 +1911,7 @@ class MainMenu : public tsl::Gui { overlayFileName = getNameFromPath(overlayFile); int priority = 0; - if (getNameFromPath(overlayFile) == "ovlmenu.ovl"){ + if (getNameFromPath(overlayFile) == "ovlmenu.ovl") { continue; } @@ -1896,36 +1919,32 @@ class MainMenu : public tsl::Gui { setIniFileValue(overlaysIniFilePath, overlayFileName, "priority", "0"); } else { // Check if the "priority" key exists in overlaysIniData for overlayFileName - if (overlaysIniData.find(overlayFileName) != overlaysIniData.end() && - overlaysIniData[overlayFileName].find("priority") != overlaysIniData[overlayFileName].end()) { + if (overlaysIniData.find(overlayFileName) != overlaysIniData.end() && overlaysIniData[overlayFileName].find("priority") != overlaysIniData[overlayFileName].end()) { priority = -(stoi(overlaysIniData[overlayFileName]["priority"])); } else - setIniFileValue(overlaysIniFilePath, overlayFileName, "priority", "0"); + setIniFileValue(overlaysIniFilePath, overlayFileName, "priority", "0"); } order.emplace(priority, overlayFileName); } - - - for (const auto & overlay : order) { + for (const auto& overlay : order) { overlayFileName = overlay.second; auto [result, overlayName, overlayVersion] = getOverlayInfo(overlayDirectory + overlayFileName); if (result != ResultSuccess) continue; - + auto* listItem = new tsl::elm::ListItem(overlayName); if (showOverlayVersions) listItem->setValue(overlayVersion); - if (sorting) { std::map> overlaysIniData = getParsedDataFromIniFile(overlaysIniFilePath); priority = std::stoi(overlaysIniData[overlayFileName]["priority"]); listItem->setValue("Priority: " + std::to_string(priority)); } // Add a click listener to load the overlay when clicked upon - listItem->setClickListener([this, overlayFile=overlayDirectory + overlayFileName, listItem, overlayFileName](s64 key) { + listItem->setClickListener([this, overlayFile = overlayDirectory + overlayFileName, listItem, overlayFileName](s64 key) { int localPriority; if (key & KEY_A) { // Load the overlay here @@ -1935,13 +1954,13 @@ class MainMenu : public tsl::Gui { return true; } else if (key & KEY_PLUS) { std::map> overlaysIniData = getParsedDataFromIniFile(overlaysIniFilePath); - localPriority = std::stoi(overlaysIniData[overlayFileName]["priority"])+1; + localPriority = std::stoi(overlaysIniData[overlayFileName]["priority"]) + 1; setIniFileValue(overlaysIniFilePath, overlayFileName, "priority", std::to_string(localPriority)); tsl::replaceWith(Soverlays); return true; } else if (key & KEY_MINUS) { std::map> overlaysIniData = getParsedDataFromIniFile(overlaysIniFilePath); - localPriority = std::stoi(overlaysIniData[overlayFileName]["priority"])-1; + localPriority = std::stoi(overlaysIniData[overlayFileName]["priority"]) - 1; setIniFileValue(overlaysIniFilePath, overlayFileName, "priority", std::to_string(localPriority)); tsl::replaceWith(Soverlays); return true; @@ -1958,100 +1977,98 @@ class MainMenu : public tsl::Gui { } //ovl updater section - if (overlayUpdater) - { - list->addItem(new tsl::elm::CategoryHeader("Updater", true)); - auto updaterItem = new tsl::elm::ListItem("Check for Overlay Updates"); - updaterItem->setClickListener([this, updaterItem](uint64_t keys) { - if (keys & KEY_A) { - if (!DownloadProcessing) { - DownloadProcessing = true; - updaterItem->setText("Processing..."); - return true; - } + if (overlayUpdater) { + list->addItem(new tsl::elm::CategoryHeader("Updater", true)); + auto updaterItem = new tsl::elm::ListItem("Check for Overlay Updates"); + updaterItem->setClickListener([this, updaterItem](uint64_t keys) { + if (keys & KEY_A) { + if (!DownloadProcessing) { + DownloadProcessing = true; + updaterItem->setText("Processing..."); + return true; } - if (DownloadProcessing) { - bool NeedUpdate = false; - std::vector> items; - if (!uberhand_updates_only) { - std::vector overlays = getFilesListByWildcard("sdmc:/switch/.overlays/*.ovl"); - std::map package; - if (downloadFile(repoUrl, "sdmc:/config/uberhand/Updater.ini")) { - auto options = loadOptionsFromIni("sdmc:/config/uberhand/Updater.ini"); - for (const std::string& overlay : overlays) { - std::string uoverlay = dropExtension(getNameFromPath(overlay)); - for (const auto& [name, parameters] : options) { - if (uoverlay == name) { - auto [result, overlayName, overlayVersion] = getOverlayInfo(overlay); - if (result != ResultSuccess) - continue; - package["name"] = overlayName; - package["filename"] = overlay; - if (parameters.size() > 1 && parameters[1].size() > 0 && parameters[1][0].starts_with("link=")) { - package["link"] = parameters[1][0].substr(5); // skip "link=" - } else { - log("Overlay Updater:ERROR: link not found for item \"%s\"", overlayName.c_str()); - break; - } - package["localVer"] = overlayVersion; - if (parameters.size() > 0 && parameters[0].size() > 0 && parameters[0][0].starts_with("downloadEntry=")) { - package["downloadEntry"] = parameters[0][0].substr(14); // skip "downloadEntry=" - } else { - log("Overlay Updater:ERROR: downloadEntry not found for item \"%s\"", overlayName.c_str()); - break; - } - std::map resultUpdate = ovlUpdateCheck(package); - if (!resultUpdate.empty()) { - NeedUpdate = true; - items.insert(items.end(), resultUpdate); - } + } + if (DownloadProcessing) { + bool NeedUpdate = false; + std::vector> items; + if (!uberhand_updates_only) { + std::vector overlays = getFilesListByWildcard("sdmc:/switch/.overlays/*.ovl"); + std::map package; + if (downloadFile(repoUrl, "sdmc:/config/uberhand/Updater.ini")) { + auto options = loadOptionsFromIni("sdmc:/config/uberhand/Updater.ini"); + for (const std::string& overlay : overlays) { + std::string uoverlay = dropExtension(getNameFromPath(overlay)); + for (const auto& [name, parameters] : options) { + if (uoverlay == name) { + auto [result, overlayName, overlayVersion] = getOverlayInfo(overlay); + if (result != ResultSuccess) + continue; + package["name"] = overlayName; + package["filename"] = overlay; + if (parameters.size() > 1 && parameters[1].size() > 0 && parameters[1][0].starts_with("link=")) { + package["link"] = parameters[1][0].substr(5); // skip "link=" + } else { + log("Overlay Updater:ERROR: link not found for item \"%s\"", overlayName.c_str()); + break; + } + package["localVer"] = overlayVersion; + if (parameters.size() > 0 && parameters[0].size() > 0 && parameters[0][0].starts_with("downloadEntry=")) { + package["downloadEntry"] = parameters[0][0].substr(14); // skip "downloadEntry=" + } else { + log("Overlay Updater:ERROR: downloadEntry not found for item \"%s\"", overlayName.c_str()); + break; + } + std::map resultUpdate = ovlUpdateCheck(package); + if (!resultUpdate.empty()) { + NeedUpdate = true; + items.insert(items.end(), resultUpdate); } } } - } else { - log("Overlay Updater:ERROR: Failed to download Updater.ini"); } } else { - auto [result, overlayName, overlayVersion] = getOverlayInfo("sdmc:/switch/.overlays/ovlmenu.ovl"); - if (result != ResultSuccess) - return false; - std::map ovlmenu; - ovlmenu["name"] = overlayName; - ovlmenu["localVer"] = overlayVersion; - ovlmenu["link"] = "https://api.github.com/repos/efosamark/Uberhand-Overlay/releases?per_page=1"; - ovlmenu["downloadEntry"] = "1"; - std::map resultUpdate = ovlUpdateCheck(ovlmenu); - if (!resultUpdate.empty()) { - NeedUpdate = true; - items.insert(items.end(), resultUpdate); - } + log("Overlay Updater:ERROR: Failed to download Updater.ini"); } - - if (NeedUpdate){ - DownloadProcessing = false; - tsl::changeTo(items); + } else { + auto [result, overlayName, overlayVersion] = getOverlayInfo("sdmc:/switch/.overlays/ovlmenu.ovl"); + if (result != ResultSuccess) + return false; + std::map ovlmenu; + ovlmenu["name"] = overlayName; + ovlmenu["localVer"] = overlayVersion; + ovlmenu["link"] = "https://api.github.com/repos/efosamark/Uberhand-Overlay/releases?per_page=1"; + ovlmenu["downloadEntry"] = "1"; + std::map resultUpdate = ovlUpdateCheck(ovlmenu); + if (!resultUpdate.empty()) { + NeedUpdate = true; + items.insert(items.end(), resultUpdate); } - updaterItem->setText("No updates"); + } + + if (NeedUpdate) { DownloadProcessing = false; - return true; + tsl::changeTo(items); } - return false; - }); - list->addItem(updaterItem); + updaterItem->setText("No updates"); + DownloadProcessing = false; + return true; + } + return false; + }); + list->addItem(updaterItem); } } - - if (menuMode == "packages" ) { + + if (menuMode == "packages") { // Create the directory if it doesn't exist createDirectory(packageDirectory); // Load options from INI file std::vector>>> options = loadOptionsFromIni(packageConfigIniPath, true); - // Load subdirectories std::vector subdirectories = getSubdirectories(packageDirectory); - + FILE* packagesIniFile = fopen(packagesIniFilePath.c_str(), "r"); if (!packagesIniFile) { fclose(fopen(packagesIniFilePath.c_str(), "w")); // The INI file doesn't exist, so create an empty one. @@ -2064,15 +2081,14 @@ class MainMenu : public tsl::Gui { for (const auto& taintedSubdirectory : subdirectories) { priority = 0; std::string subWithoutSpaces = taintedSubdirectory; - std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); + (void)std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); if (packagesIniData.find(subWithoutSpaces) == packagesIniData.end()) { setIniFileValue(packagesIniFilePath, subWithoutSpaces, "priority", "0"); } else { - if (packagesIniData.find(subWithoutSpaces) != packagesIniData.end() && - packagesIniData[subWithoutSpaces].find("priority") != packagesIniData[subWithoutSpaces].end()) { + if (packagesIniData.find(subWithoutSpaces) != packagesIniData.end() && packagesIniData[subWithoutSpaces].find("priority") != packagesIniData[subWithoutSpaces].end()) { priority = -(stoi(packagesIniData[subWithoutSpaces]["priority"])); } else - setIniFileValue(packagesIniFilePath, subWithoutSpaces, "priority", "0"); + setIniFileValue(packagesIniFilePath, subWithoutSpaces, "priority", "0"); } // log("priority, taintedSubdirectory: "+std::to_string(priority)+subWithoutSpaces); order.emplace(priority, taintedSubdirectory); @@ -2084,18 +2100,17 @@ class MainMenu : public tsl::Gui { //bool usingStar = false; std::string subdirectory = package.second; std::string subdirectoryIcon = ""; - std::string subPath = packageDirectory + subdirectory + "/"; std::string configFilePath = subPath + "config.ini"; - + if (isFileOrDirectory(configFilePath)) { PackageHeader packageHeader = getPackageHeaderFromIni(subPath + configFileName); if (count == 0) { // Add a section break with small text to indicate the "Packages" section list->addItem(new tsl::elm::CategoryHeader("Packages")); } - + auto listItem = new tsl::elm::ListItem(subdirectoryIcon + subdirectory); if (showPackageVersions) listItem->setValue(packageHeader.version); @@ -2104,7 +2119,7 @@ class MainMenu : public tsl::Gui { if (sorting) { std::map> packagesIniData = getParsedDataFromIniFile(packagesIniFilePath); subWithoutSpaces = subdirectory; - std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); + (void)std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); priority = std::stoi(packagesIniData[subWithoutSpaces]["priority"]); listItem->setValue("Priority: " + std::to_string(priority)); } @@ -2125,33 +2140,33 @@ class MainMenu : public tsl::Gui { } else if (keys & KEY_PLUS) { std::map> packagesIniData = getParsedDataFromIniFile(packagesIniFilePath); subWithoutSpaces = subdirectory; - std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); - localPriority = std::stoi(packagesIniData[subWithoutSpaces]["priority"])+1; + (void)std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); + localPriority = std::stoi(packagesIniData[subWithoutSpaces]["priority"]) + 1; setIniFileValue(packagesIniFilePath, subWithoutSpaces, "priority", std::to_string(localPriority)); tsl::replaceWith(Spackages); return true; } else if (keys & KEY_MINUS) { std::map> packagesIniData = getParsedDataFromIniFile(packagesIniFilePath); subWithoutSpaces = subdirectory; - std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); - localPriority = std::stoi(packagesIniData[subWithoutSpaces]["priority"])-1; + (void)std::remove(subWithoutSpaces.begin(), subWithoutSpaces.end(), ' '); + localPriority = std::stoi(packagesIniData[subWithoutSpaces]["priority"]) - 1; setIniFileValue(packagesIniFilePath, subWithoutSpaces, "priority", std::to_string(localPriority)); tsl::replaceWith(Spackages); return true; } if (DownloadProcessing) { std::vector>>> options = loadOptionsFromIni(subPath + "/init.ini"); - for (const auto& option : options) { - if (interpretAndExecuteCommand(getModifyCommands(option.second, subPath + option.first)) == -1) { - log("Init failed!"); - DownloadProcessing = false; - listItem->setValue("FAIL", tsl::PredefinedColors::Red); - } else { - deleteFileOrDirectory(subPath + "/init.ini"); - DownloadProcessing = false; - tsl::changeTo(subPath); - } + for (const auto& option : options) { + if (interpretAndExecuteCommand(getModifyCommands(option.second, subPath + option.first)) == -1) { + log("Init failed!"); + DownloadProcessing = false; + listItem->setValue("FAIL", tsl::PredefinedColors::Red); + } else { + deleteFileOrDirectory(subPath + "/init.ini"); + DownloadProcessing = false; + tsl::changeTo(subPath); } + } } return false; }); @@ -2159,43 +2174,41 @@ class MainMenu : public tsl::Gui { list->addItem(listItem); count++; } - } //package updater section - if (packageUpdater) - { + if (packageUpdater) { list->addItem(new tsl::elm::CategoryHeader("Updater", true)); auto updaterItem = new tsl::elm::ListItem("Check for Package Updates"); updaterItem->setClickListener([this, subdirectories, updaterItem](uint64_t keys) { - if (keys & KEY_A) { - if (!DownloadProcessing) { - DownloadProcessing = true; - updaterItem->setText("Processing..."); - return true; - } - } - if (DownloadProcessing) { - bool NeedUpdate = false; - std::vector> items; - for (const auto& taintedSubdirectory : subdirectories) { - std::map packageInfo = packageUpdateCheck(taintedSubdirectory + "/config.ini"); - if (packageInfo["localVer"] != packageInfo["repoVer"]) { - NeedUpdate = true; - packageInfo["filename"] = packageDirectory + taintedSubdirectory; - items.insert(items.end(), packageInfo); - } - } - if (NeedUpdate){ - DownloadProcessing = false; - tsl::changeTo(items); - } - DownloadProcessing = false; - updaterItem->setText("No updates"); - return true; + if (keys & KEY_A) { + if (!DownloadProcessing) { + DownloadProcessing = true; + updaterItem->setText("Processing..."); + return true; + } + } + if (DownloadProcessing) { + bool NeedUpdate = false; + std::vector> items; + for (const auto& taintedSubdirectory : subdirectories) { + std::map packageInfo = packageUpdateCheck(taintedSubdirectory + "/config.ini"); + if (packageInfo["localVer"] != packageInfo["repoVer"]) { + NeedUpdate = true; + packageInfo["filename"] = packageDirectory + taintedSubdirectory; + items.insert(items.end(), packageInfo); } - return false; - }); + } + if (NeedUpdate) { + DownloadProcessing = false; + tsl::changeTo(items); + } + DownloadProcessing = false; + updaterItem->setText("No updates"); + return true; + } + return false; + }); list->addItem(updaterItem); } count = 0; @@ -2203,7 +2216,7 @@ class MainMenu : public tsl::Gui { // Populate the menu with options for (const auto& option : options) { optionName = option.first; - + // Check if it's a subdirectory fullPath = packageDirectory + optionName; if (count == 0) { @@ -2216,7 +2229,7 @@ class MainMenu : public tsl::Gui { list->addItem(item); continue; } - + //std::string header; //if ((optionName == "Shutdown")) { // header = "\uE0F3 "; @@ -2226,7 +2239,7 @@ class MainMenu : public tsl::Gui { //} //auto listItem = new tsl::elm::ListItem(header+optionName); auto listItem = new tsl::elm::ListItem(optionName); - + std::vector> modifiedCommands = getModifyCommands(option.second, fullPath); listItem->setClickListener([this, command = modifiedCommands, subPath = optionName, listItem](uint64_t keys) { if (keys & KEY_A) { @@ -2249,7 +2262,7 @@ class MainMenu : public tsl::Gui { return true; } else if (keys && (listItem->getValue() == "DONE" || listItem->getValue() == "FAIL")) { - listItem->setValue(""); + listItem->setValue(""); } return false; }); @@ -2263,16 +2276,17 @@ class MainMenu : public tsl::Gui { return rootFrame; } - + bool adjuct_top, adjuct_bot = false; - virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override { + virtual bool handleInput(uint64_t keysDown, uint64_t keysHeld, touchPosition touchInput, JoystickPosition leftJoyStick, JoystickPosition rightJoyStick) override + { if (this->adjuct_top) { // Adjust cursor to the top item after jump bot-top this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); this->adjuct_top = false; return true; } - if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot + if (this->adjuct_bot) { // Adjust cursor to the top item after jump top-bot this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); this->adjuct_bot = false; return true; @@ -2283,7 +2297,7 @@ class MainMenu : public tsl::Gui { this->requestFocus(this->getTopElement(), tsl::FocusDirection::Down); if (prevItem == this->getFocusedElement()) { scrollListItems(this, ShiftFocusMode::UpMax); - this->adjuct_top = true; // Go one item + this->adjuct_top = true; // Go one item } else { // Adjust to account for tesla key processing this->requestFocus(this->getTopElement(), tsl::FocusDirection::Up); } @@ -2308,7 +2322,8 @@ class MainMenu : public tsl::Gui { if (keysDown & KEY_R) { // Scroll to down for 5 items scrollListItems(this, ShiftFocusMode::DownNum); return true; - }if (keysDown & KEY_ZL) { // Scroll to up for 5 items + } + if (keysDown & KEY_ZL) { // Scroll to up for 5 items scrollListItems(this, ShiftFocusMode::UpMax); return true; } @@ -2340,8 +2355,8 @@ class MainMenu : public tsl::Gui { class Overlay : public tsl::Overlay { public: - - virtual void initServices() override { + virtual void initServices() override + { fsdevMountSdmc(); splInitialize(); spsmInitialize(); @@ -2351,7 +2366,8 @@ class Overlay : public tsl::Overlay { ASSERT_FATAL(smInitialize()); } - virtual void exitServices() override { + virtual void exitServices() override + { socketExit(); nifmExit(); timeExit(); @@ -2361,22 +2377,23 @@ class Overlay : public tsl::Overlay { fsdevUnmountAll(); } - virtual void onShow() override { + virtual void onShow() override + { //if (rootFrame != nullptr) { // tsl::Overlay::get()->getCurrentGui()->removeFocus(); // rootFrame->invalidate(); // tsl::Overlay::get()->getCurrentGui()->requestFocus(rootFrame, tsl::FocusDirection::None); //} - } // Called before overlay wants to change from invisible to visible state - virtual void onHide() override {} // Called before overlay wants to change from visible to invisible state + } // Called before overlay wants to change from invisible to visible state + virtual void onHide() override { } // Called before overlay wants to change from visible to invisible state - virtual std::unique_ptr loadInitialGui() override { - return initially(); // Initial Gui to load. It's possible to pass arguments to its constructor like this + virtual std::unique_ptr loadInitialGui() override + { + return initially(); // Initial Gui to load. It's possible to pass arguments to its constructor like this } }; - - -int main(int argc, char* argv[]) { +int main(int argc, char* argv[]) +{ return tsl::loop(argc, argv); } diff --git a/source/path_funcs.hpp b/source/path_funcs.hpp index a7d1808c..703e1784 100644 --- a/source/path_funcs.hpp +++ b/source/path_funcs.hpp @@ -1,14 +1,17 @@ #pragma once -#include + #include +#include + #include -#include +#include #include +#include #include -#include // Function to create a directory if it doesn't exist -void createSingleDirectory(const std::string& directoryPath) { +void createSingleDirectory(const std::string& directoryPath) +{ struct stat st; if (stat(directoryPath.c_str(), &st) != 0) { mkdir(directoryPath.c_str(), 0777); @@ -16,7 +19,8 @@ void createSingleDirectory(const std::string& directoryPath) { } // Function to create a directory (including nested directories) if it doesn't exist -void createDirectory(const std::string& directoryPath) { +void createDirectory(const std::string& directoryPath) +{ std::string path = directoryPath; // Remove leading "sdmc:/" if present @@ -49,12 +53,9 @@ void createDirectory(const std::string& directoryPath) { } } - - - - // Function to create a text file with the specified content -void createTextFile(const std::string& filePath, const std::string& content) { +void createTextFile(const std::string& filePath, const std::string& content) +{ FILE* file = std::fopen(filePath.c_str(), "w"); if (file != nullptr) { std::fwrite(content.c_str(), 1, content.length(), file); @@ -62,16 +63,17 @@ void createTextFile(const std::string& filePath, const std::string& content) { } } - -void removeEntryFromList(const std::string& entry, std::vector& fileList) { +void removeEntryFromList(const std::string& entry, std::vector& fileList) +{ fileList.erase(std::remove_if(fileList.begin(), fileList.end(), [&](const std::string& filePath) { - return filePath.compare(0, entry.length(), entry) == 0; - }), fileList.end()); + return filePath.compare(0, entry.length(), entry) == 0; + }), + fileList.end()); } - // Delete functions -bool deleteFileOrDirectory(const std::string& pathToDelete) { +bool deleteFileOrDirectory(const std::string& pathToDelete) +{ struct stat pathStat; if (isDirectory(pathToDelete)) { @@ -96,7 +98,8 @@ bool deleteFileOrDirectory(const std::string& pathToDelete) { return false; } -bool deleteFileOrDirectoryByPattern(const std::string& pathPattern) { +bool deleteFileOrDirectoryByPattern(const std::string& pathPattern) +{ //log("pathPattern: "+pathPattern); std::vector fileList = getFilesListByWildcards(pathPattern); bool result = true; @@ -104,13 +107,14 @@ bool deleteFileOrDirectoryByPattern(const std::string& pathPattern) { //log("path: "+path); result = result && deleteFileOrDirectory(path); if (!result) { - return result; + return result; } } return result; } -bool mirrorDeleteFiles(const std::string& sourcePath, const std::string& targetPath="sdmc:/") { +bool mirrorDeleteFiles(const std::string& sourcePath, const std::string& targetPath = "sdmc:/") +{ std::vector fileList = getFilesListFromDirectory(sourcePath); bool result = true; for (const auto& path : fileList) { @@ -126,15 +130,15 @@ bool mirrorDeleteFiles(const std::string& sourcePath, const std::string& targetP return result; } - // Move functions -bool moveFileOrDirectory(const std::string& sourcePath, const std::string& destinationPath) { +bool moveFileOrDirectory(const std::string& sourcePath, const std::string& destinationPath) +{ struct stat sourceInfo; struct stat destinationInfo; - + //log("sourcePath: "+sourcePath); //log("destinationPath: "+destinationPath); - + if (stat(sourcePath.c_str(), &sourceInfo) == 0) { // Source file or directory exists @@ -143,7 +147,7 @@ bool moveFileOrDirectory(const std::string& sourcePath, const std::string& desti if (!destinationExists) { // Create the destination directory createDirectory(getParentDirFromPath(destinationPath)); - } + } if (S_ISDIR(sourceInfo.st_mode)) { // Source path is a directory @@ -187,11 +191,10 @@ bool moveFileOrDirectory(const std::string& sourcePath, const std::string& desti if (destinationPath[destinationPath.length() - 1] == '/') { destinationFilePath += filename; } - - + //log("sourcePath: "+sourcePath); //log("destinationFilePath: "+destinationFilePath); - + deleteFileOrDirectory(destinationFilePath); // delete destiantion file for overwriting if (rename(sourcePath.c_str(), destinationFilePath.c_str()) == -1) { //printf("Failed to move file: %s\n", sourcePath.c_str()); @@ -207,7 +210,8 @@ bool moveFileOrDirectory(const std::string& sourcePath, const std::string& desti return false; } -bool moveFilesOrDirectoriesByPattern(const std::string& sourcePathPattern, const std::string& destinationPath) { +bool moveFilesOrDirectoriesByPattern(const std::string& sourcePathPattern, const std::string& destinationPath) +{ std::vector fileList = getFilesListByWildcards(sourcePathPattern); bool result = true; std::string fileListAsString; @@ -215,7 +219,7 @@ bool moveFilesOrDirectoriesByPattern(const std::string& sourcePathPattern, const fileListAsString += filePath + "\n"; } //log("File List:\n" + fileListAsString); - + //log("pre loop"); // Iterate through the file list for (const std::string& sourceFileOrDirectory : fileList) { @@ -231,23 +235,22 @@ bool moveFilesOrDirectoriesByPattern(const std::string& sourcePathPattern, const // if sourceFile is a directory (needs conditoin handling) std::string folderName = getNameFromPath(sourceFileOrDirectory); std::string fixedDestinationPath = destinationPath + folderName + "/"; - + //log("fixedDestinationPath: "+fixedDestinationPath); - + result = result && moveFileOrDirectory(sourceFileOrDirectory, fixedDestinationPath); if (!result) { return result; } } - } return result; //log("post loop"); } - // Copy functions -bool copySingleFile(const std::string& fromFile, const std::string& toFile) { +bool copySingleFile(const std::string& fromFile, const std::string& toFile) +{ FILE* srcFile = fopen(fromFile.c_str(), "rb"); FILE* destFile = fopen(toFile.c_str(), "wb"); if (srcFile && destFile) { @@ -269,16 +272,17 @@ bool copySingleFile(const std::string& fromFile, const std::string& toFile) { return true; } -bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::string& toFileOrDirectory) { +bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::string& toFileOrDirectory) +{ bool result = true; struct stat fromFileOrDirectoryInfo; if (stat(fromFileOrDirectory.c_str(), &fromFileOrDirectoryInfo) == 0) { if (S_ISREG(fromFileOrDirectoryInfo.st_mode)) { // Source is a regular file std::string fromFile = fromFileOrDirectory; - + struct stat toFileOrDirectoryInfo; - + if (stat(toFileOrDirectory.c_str(), &toFileOrDirectoryInfo) == 0 && S_ISDIR(toFileOrDirectoryInfo.st_mode)) { // Destination is a directory std::string toDirectory = toFileOrDirectory; @@ -301,7 +305,7 @@ bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::stri // Create the destination directory if it doesn't exist createDirectory(toDirectory); - + // Destination is a file or doesn't exist // Check if the destination file exists and remove it if (stat(toFile.c_str(), &toFileOrDirectoryInfo) == 0 && S_ISREG(toFileOrDirectoryInfo.st_mode)) { @@ -314,14 +318,14 @@ bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::stri // Source is a directory std::string fromDirectory = fromFileOrDirectory; //log("fromDirectory: "+fromDirectory); - + struct stat toFileOrDirectoryInfo; if (stat(toFileOrDirectory.c_str(), &toFileOrDirectoryInfo) == 0 && S_ISDIR(toFileOrDirectoryInfo.st_mode)) { // Destination is a directory std::string toDirectory = toFileOrDirectory; std::string dirName = getNameFromPath(fromDirectory); if (dirName != "") { - std::string toDirPath = toDirectory + dirName +"/"; + std::string toDirPath = toDirectory + dirName + "/"; //log("toDirectory: "+toDirectory); //log("dirName: "+dirName); //log("toDirPath: "+toDirPath); @@ -347,17 +351,16 @@ bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::stri } // handle case for subfolders within the from file path if (entry->d_type == DT_DIR && fileOrFolderName != "." && fileOrFolderName != "..") { - std::string subFolderPath = fromDirectory + fileOrFolderName + "/"; + std::string subFolderPath = fromDirectory + fileOrFolderName + "/"; result = result && copyFileOrDirectory(subFolderPath, toDirPath); if (!result) { closedir(dir); return result; } } - } closedir(dir); - } + } } } } @@ -365,14 +368,15 @@ bool copyFileOrDirectory(const std::string& fromFileOrDirectory, const std::stri return result; } -bool copyFileOrDirectoryByPattern(const std::string& sourcePathPattern, const std::string& toDirectory) { +bool copyFileOrDirectoryByPattern(const std::string& sourcePathPattern, const std::string& toDirectory) +{ std::vector fileList = getFilesListByWildcards(sourcePathPattern); bool result = true; for (const std::string& sourcePath : fileList) { //log("sourcePath: "+sourcePath); //log("toDirectory: "+toDirectory); - if (sourcePath != toDirectory){ + if (sourcePath != toDirectory) { result = result && copyFileOrDirectory(sourcePath, toDirectory); if (!result) { return result; @@ -380,19 +384,19 @@ bool copyFileOrDirectoryByPattern(const std::string& sourcePathPattern, const st } else { return false; } - } return result; } -bool mirrorCopyFiles(const std::string& sourcePath, const std::string& targetPath="sdmc:/") { +bool mirrorCopyFiles(const std::string& sourcePath, const std::string& targetPath = "sdmc:/") +{ std::vector fileList = getFilesListFromDirectory(sourcePath); bool result = true; for (const auto& path : fileList) { // Generate the corresponding path in the target directory by replacing the source path std::string updatedPath = targetPath + path.substr(sourcePath.size()); - if (path != updatedPath){ + if (path != updatedPath) { //log("mirror-copy: "+path+" "+updatedPath); result = result && copyFileOrDirectory(path, updatedPath); if (!result) { @@ -405,7 +409,8 @@ bool mirrorCopyFiles(const std::string& sourcePath, const std::string& targetPat return result; } -bool generateBackup() { +bool generateBackup() +{ int highestNumber = 0; std::regex pattern(R"(Backup \[(\d+)\])"); namespace fs = std::filesystem; diff --git a/source/string_funcs.hpp b/source/string_funcs.hpp index 798de526..4f66aa19 100644 --- a/source/string_funcs.hpp +++ b/source/string_funcs.hpp @@ -1,10 +1,12 @@ #pragma once + #include constexpr const char* WhitespaceCharacters = " \t\n\r\f\v"; // Trim leading and trailing whitespaces from a string -static std::string trim(const std::string& str) { +static std::string trim(const std::string& str) +{ size_t first = str.find_first_not_of(WhitespaceCharacters); size_t last = str.find_last_not_of(WhitespaceCharacters); if (first == std::string::npos || last == std::string::npos) { @@ -14,7 +16,8 @@ static std::string trim(const std::string& str) { } // In-place trimming of whitespace characters for rvalue strings -static inline std::string trim(std::string&& str) { +static inline std::string trim(std::string&& str) +{ const size_t first = str.find_first_not_of(WhitespaceCharacters); if (first == std::string::npos) { return ""; @@ -25,7 +28,8 @@ static inline std::string trim(std::string&& str) { } // In-place trimming of whitespace characters -static inline void trimInPlace(std::string& str) { +static inline void trimInPlace(std::string& str) +{ const size_t first = str.find_first_not_of(WhitespaceCharacters); if (first == std::string::npos) { str.erase(); @@ -35,7 +39,8 @@ static inline void trimInPlace(std::string& str) { str.erase(str.find_last_not_of(WhitespaceCharacters) + 1); } -std::string removeQuotes(const std::string& str) { +std::string removeQuotes(const std::string& str) +{ std::size_t firstQuote = str.find_first_of("'\""); std::size_t lastQuote = str.find_last_of("'\""); if (firstQuote != std::string::npos && lastQuote != std::string::npos && firstQuote < lastQuote) { @@ -44,8 +49,8 @@ std::string removeQuotes(const std::string& str) { return str; } - -std::string replaceMultipleSlashes(const std::string& input) { +std::string replaceMultipleSlashes(const std::string& input) +{ std::string output; bool previousSlash = false; @@ -64,22 +69,24 @@ std::string replaceMultipleSlashes(const std::string& input) { return output; } -std::string removeLeadingSlash(const std::string& pathPattern) { +std::string removeLeadingSlash(const std::string& pathPattern) +{ if (!pathPattern.empty() && pathPattern[0] == '/') { return pathPattern.substr(1); } return pathPattern; } -std::string removeEndingSlash(const std::string& pathPattern) { +std::string removeEndingSlash(const std::string& pathPattern) +{ if (!pathPattern.empty() && pathPattern.back() == '/') { return pathPattern.substr(0, pathPattern.length() - 1); } return pathPattern; } - -std::string preprocessPath(const std::string& path) { +std::string preprocessPath(const std::string& path) +{ std::string formattedPath = replaceMultipleSlashes(removeQuotes(path)); if (formattedPath.compare(0, 5, "sdmc:") != 0) { return std::string("sdmc:") + formattedPath; @@ -88,8 +95,8 @@ std::string preprocessPath(const std::string& path) { } } - -std::string preprocessUrl(const std::string& path) { +std::string preprocessUrl(const std::string& path) +{ std::string formattedPath = removeQuotes(path); if ((formattedPath.compare(0, 7, "http://") == 0) || (formattedPath.compare(0, 8, "https://") == 0)) { return formattedPath; @@ -98,7 +105,8 @@ std::string preprocessUrl(const std::string& path) { } } -std::string dropExtension(const std::string& filename) { +std::string dropExtension(const std::string& filename) +{ size_t lastDotPos = filename.find_last_of("."); if (lastDotPos != std::string::npos) { return filename.substr(0, lastDotPos); @@ -106,7 +114,8 @@ std::string dropExtension(const std::string& filename) { return filename; } -std::string getExtension(const std::string& filename) { +std::string getExtension(const std::string& filename) +{ size_t lastDotPos = filename.find_last_of("."); if (lastDotPos != std::string::npos) { return filename.substr(lastDotPos + 1); @@ -114,29 +123,33 @@ std::string getExtension(const std::string& filename) { return filename; } -bool startsWith(const std::string& str, const std::string& prefix) { +bool startsWith(const std::string& str, const std::string& prefix) +{ return str.compare(0, prefix.length(), prefix) == 0; } // Path functions -bool isDirectory(const std::string& path) { +bool isDirectory(const std::string& path) +{ struct stat pathStat; if (stat(path.c_str(), &pathStat) == 0) { return S_ISDIR(pathStat.st_mode); } return false; } -bool isFileOrDirectory(const std::string& path) { +bool isFileOrDirectory(const std::string& path) +{ struct stat buffer; return (stat(path.c_str(), &buffer) == 0); } -std::string getSubstringAfterLastSlash(const std::string& str) { +std::string getSubstringAfterLastSlash(const std::string& str) +{ size_t lastSlashPos = str.rfind('/'); - + if (lastSlashPos != std::string::npos) { return str.substr(lastSlashPos + 1); } - + return ""; } \ No newline at end of file diff --git a/source/text_funcs.hpp b/source/text_funcs.hpp index 3486b2fe..89377070 100644 --- a/source/text_funcs.hpp +++ b/source/text_funcs.hpp @@ -1,9 +1,12 @@ +#pragma once + +#include #include #include -#include #include -std::pair readTextFromFile (const std::string& filePath) { +std::pair readTextFromFile(const std::string& filePath) +{ // log("Entered readTextFromFile"); std::string lines; @@ -20,7 +23,7 @@ std::pair readTextFromFile (const std::string& filePath) { lineCount++; continue; } - + std::istringstream lineStream(line); std::string word; std::string currentLine; @@ -47,68 +50,70 @@ std::pair readTextFromFile (const std::string& filePath) { return std::make_pair(lines, lineCount); } -bool write_to_file(const std::string& file_path, const std::string& line) { - std::ifstream file(file_path); - if (!file.is_open()) { - // File doesn't exist, create it +bool write_to_file(const std::string& file_path, const std::string& line) +{ + std::ifstream file(file_path); + if (!file.is_open()) { + // File doesn't exist, create it + std::ofstream output_file(file_path); + if (!output_file.is_open()) { + log("Error opening file: %s", file_path.c_str()); + return false; + } + output_file << line << std::endl; + return true; + } + + std::string existing_line; + std::vector existing_lines; + while (std::getline(file, existing_line)) { + existing_lines.push_back(existing_line); + } + file.close(); + + if (std::find(existing_lines.begin(), existing_lines.end(), line) != existing_lines.end()) { + return true; // Line already exists, no need to write it again + } + + existing_lines.push_back(line); + std::ofstream output_file(file_path); if (!output_file.is_open()) { - log("Error opening file: %s", file_path.c_str()); - return false; + log("Error opening file: %s", file_path.c_str()); + return false; + } + + for (const auto& existing_line : existing_lines) { + output_file << existing_line << std::endl; } - output_file << line << std::endl; return true; - } - - std::string existing_line; - std::vector existing_lines; - while (std::getline(file, existing_line)) { - existing_lines.push_back(existing_line); - } - file.close(); - - if (std::find(existing_lines.begin(), existing_lines.end(), line) != existing_lines.end()) { - return true; // Line already exists, no need to write it again - } - - existing_lines.push_back(line); - - std::ofstream output_file(file_path); - if (!output_file.is_open()) { - log("Error opening file: %s", file_path.c_str()); - return false; - } - - for (const auto& existing_line : existing_lines) { - output_file << existing_line << std::endl; - } - return true; } -bool remove_txt(const std::string& file_path, const std::string& pattern) { - std::vector lines; - std::ifstream file(file_path); - if (!file.is_open()) { - log("File %s not found", file_path.c_str()); - return true; - } +bool remove_txt(const std::string& file_path, const std::string& pattern) +{ + std::vector lines; + std::ifstream file(file_path); + if (!file.is_open()) { + log("File %s not found", file_path.c_str()); + return true; + } - std::string line; - while (std::getline(file, line)) { - if (line.find(pattern) == std::string::npos) { - lines.push_back(line); + std::string line; + while (std::getline(file, line)) { + if (line.find(pattern) == std::string::npos) { + lines.push_back(line); + } } - } - file.close(); + file.close(); - std::ofstream output_file(file_path); - if (!output_file.is_open()) { - log("File %s can't be created", file_path.c_str()); - return true; - } + std::ofstream output_file(file_path); + if (!output_file.is_open()) { + log("File %s can't be created", file_path.c_str()); + return true; + } - for (const auto& line : lines) { - output_file << line << std::endl; - } - return true; + for (const auto& line : lines) { + output_file << line << std::endl; + } + return true; } \ No newline at end of file diff --git a/source/utils.hpp b/source/utils.hpp index 9a366719..9879e1cb 100644 --- a/source/utils.hpp +++ b/source/utils.hpp @@ -1,16 +1,17 @@ #pragma once -#include -#include + #include +#include #include #include -#include -#include #include -#include +#include +#include #include +#include +#include +#include #include -#include #define SpsmShutdownMode_Normal 0 #define SpsmShutdownMode_Reboot 1 @@ -47,7 +48,7 @@ const std::string settingsPath = "sdmc:/config/uberhand/"; const std::string settingsConfigIniPath = settingsPath + configFileName; const std::string packageDirectory = "sdmc:/switch/.packages/"; const std::string overlayDirectory = "sdmc:/switch/.overlays/"; -const std::string teslaSettingsConfigIniPath = "sdmc:/config/tesla/"+configFileName; +const std::string teslaSettingsConfigIniPath = "sdmc:/config/tesla/" + configFileName; const std::string overlaysIniFilePath = settingsPath + "overlays.ini"; const std::string packagesIniFilePath = settingsPath + "packages.ini"; const std::string checkmarkChar = "\uE14B"; @@ -63,30 +64,30 @@ enum ShiftFocusMode { DownMax }; -void scrollListItems(tsl::Gui* gui, ShiftFocusMode mode) { +void scrollListItems(tsl::Gui* gui, ShiftFocusMode mode) +{ int i = 0; int scrollItemNum = 0; tsl::FocusDirection dir; - switch (mode) - { - case ShiftFocusMode::UpNum: - scrollItemNum = 4; - dir = tsl::FocusDirection::Up; - break; - case ShiftFocusMode::DownNum: - scrollItemNum = 4; - dir = tsl::FocusDirection::Down; - break; - case ShiftFocusMode::UpMax: - scrollItemNum = 10000; - dir = tsl::FocusDirection::Up; - break; - case ShiftFocusMode::DownMax: - scrollItemNum = 10000; - dir = tsl::FocusDirection::Down; - break; - default: - return; + switch (mode) { + case ShiftFocusMode::UpNum: + scrollItemNum = 4; + dir = tsl::FocusDirection::Up; + break; + case ShiftFocusMode::DownNum: + scrollItemNum = 4; + dir = tsl::FocusDirection::Down; + break; + case ShiftFocusMode::UpMax: + scrollItemNum = 10000; + dir = tsl::FocusDirection::Up; + break; + case ShiftFocusMode::DownMax: + scrollItemNum = 10000; + dir = tsl::FocusDirection::Down; + break; + default: + return; } do { gui->requestFocus(gui->getTopElement(), dir); @@ -94,10 +95,11 @@ void scrollListItems(tsl::Gui* gui, ShiftFocusMode mode) { } while (i < scrollItemNum); } -void copyTeslaKeyComboTouberhand() { +void copyTeslaKeyComboTouberhand() +{ std::string keyCombo; IniData parsedData; - + if (isFileOrDirectory(teslaSettingsConfigIniPath)) { parsedData = getParsedDataFromIniFile(teslaSettingsConfigIniPath); if (parsedData.count("tesla") > 0) { @@ -107,8 +109,8 @@ void copyTeslaKeyComboTouberhand() { } } } - - if (!keyCombo.empty()){ + + if (!keyCombo.empty()) { if (isFileOrDirectory(settingsConfigIniPath)) { parsedData = getParsedDataFromIniFile(settingsConfigIniPath); if (parsedData.count("uberhand") > 0) { @@ -123,8 +125,6 @@ void copyTeslaKeyComboTouberhand() { tsl::impl::parseOverlaySettings(); } - - // Safety conditions // List of protected folders const std::vector protectedFolders = { @@ -140,17 +140,18 @@ const std::vector ultraProtectedFolders = { "sdmc:/Nintendo/", "sdmc:/emuMMC/" }; -bool isDangerousCombination(const std::string& patternPath) { +bool isDangerousCombination(const std::string& patternPath) +{ // List of obviously dangerous patterns const std::vector dangerousCombinationPatterns = { - "*", // Deletes all files/directories in the current directory - "*/" // Deletes all files/directories in the current directory + "*", // Deletes all files/directories in the current directory + "*/" // Deletes all files/directories in the current directory }; // List of obviously dangerous patterns const std::vector dangerousPatterns = { - "..", // Attempts to traverse to parent directories - "~" // Represents user's home directory, can be dangerous if misused + "..", // Attempts to traverse to parent directories + "~" // Represents user's home directory, can be dangerous if misused }; // Check if the patternPath is an ultra protected folder @@ -269,12 +270,13 @@ struct ThreadArgs { // Main interpreter int interpretAndExecuteCommand(const std::vector>& commands, std::string progress = "", - tsl::elm::ListItem* listItem = nullptr) { + tsl::elm::ListItem* listItem = nullptr) +{ std::string commandName, jsonPath, sourcePath, destinationPath, desiredSection, desiredKey, desiredNewKey, desiredValue, offset, hexDataToReplace, hexDataReplacement, fileUrl, occurrence; bool catchErrors = false; int curProgress = 0; for (auto& unmodifiedCommand : commands) { - + // Check the command and perform the appropriate action if (unmodifiedCommand.empty()) { // Empty command, do nothing @@ -285,10 +287,9 @@ int interpretAndExecuteCommand(const std::vector>& comm commandName = unmodifiedCommand[0]; //log(commandName); //log(command[1]); - - + std::vector command; - + // Modify the command to replace {json_data} placeholder if jsonPath is available if (!jsonPath.empty()) { std::vector modifiedCommand; @@ -307,7 +308,7 @@ int interpretAndExecuteCommand(const std::vector>& comm } else { command = unmodifiedCommand; } - + // if (commandName == "json-set-current") { // if (command.size() >= 2) { // jsonPath = preprocessPath(command[1]); @@ -343,8 +344,8 @@ int interpretAndExecuteCommand(const std::vector>& comm destinationPath = preprocessPath(command[2]); bool result; if (sourcePath.find('*') != std::string::npos) { - // Copy files or directories by pattern - result = copyFileOrDirectoryByPattern(sourcePath, destinationPath); + // Copy files or directories by pattern + result = copyFileOrDirectoryByPattern(sourcePath, destinationPath); } else { result = copyFileOrDirectory(sourcePath, destinationPath); } @@ -377,7 +378,7 @@ int interpretAndExecuteCommand(const std::vector>& comm if (command.size() >= 2) { bool result; if (command[1] != "") { - sourcePath = preprocessPath(command[1]); + sourcePath = preprocessPath(command[1]); if (!isDangerousCombination(sourcePath)) { if (sourcePath.find('*') != std::string::npos) { // Delete files or directories by pattern @@ -416,7 +417,7 @@ int interpretAndExecuteCommand(const std::vector>& comm destinationPath = preprocessPath(command[2]); //log("sourcePath: "+sourcePath); //log("destinationPath: "+destinationPath); - + if (!isDangerousCombination(sourcePath)) { if (sourcePath.find('*') != std::string::npos) { // Move files by pattern @@ -483,7 +484,7 @@ int interpretAndExecuteCommand(const std::vector>& comm } } - bool result = setIniFileKey(sourcePath, desiredSection, desiredKey, desiredNewKey); + bool result = setIniFileKey(sourcePath, desiredSection, desiredKey, desiredNewKey); if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); return -1; @@ -505,7 +506,7 @@ int interpretAndExecuteCommand(const std::vector>& comm desiredSection = removeQuotes(command[2]); desiredKey = removeQuotes(command[3]); - bool result = removeIniFileKey(sourcePath, desiredSection, desiredKey); + bool result = removeIniFileKey(sourcePath, desiredSection, desiredKey); if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); return -1; @@ -515,7 +516,7 @@ int interpretAndExecuteCommand(const std::vector>& comm // Edit command if (command.size() == 3) { sourcePath = preprocessPath(command[1]); - bool result = remove_txt(sourcePath, removeQuotes(command[2])); + bool result = remove_txt(sourcePath, removeQuotes(command[2])); // log(command[2]); if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); @@ -526,7 +527,7 @@ int interpretAndExecuteCommand(const std::vector>& comm // Edit command if (command.size() == 3) { sourcePath = preprocessPath(command[1]); - bool result = write_to_file(sourcePath, removeQuotes(command[2])); + bool result = write_to_file(sourcePath, removeQuotes(command[2])); // log(command[2]); if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); @@ -557,9 +558,9 @@ int interpretAndExecuteCommand(const std::vector>& comm if (command.size() >= 5) { occurrence = removeQuotes(command[4]); - result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement, occurrence); + result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement, occurrence); } else { - result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement); + result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement); } if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); @@ -575,7 +576,7 @@ int interpretAndExecuteCommand(const std::vector>& comm hexDataReplacement = asciiToHex(removeQuotes(command[3])); //log("hexDataToReplace: "+hexDataToReplace); //log("hexDataReplacement: "+hexDataReplacement); - + // Fix miss-matched string sizes if (hexDataReplacement.length() < hexDataToReplace.length()) { // Pad with spaces at the end @@ -584,12 +585,12 @@ int interpretAndExecuteCommand(const std::vector>& comm // Add spaces to hexDataToReplace at the far right end hexDataToReplace += std::string(hexDataReplacement.length() - hexDataToReplace.length(), '\0'); } - + if (command.size() >= 5) { occurrence = removeQuotes(command[4]); - result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement, occurrence); + result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement, occurrence); } else { - result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement); + result = hexEditFindReplace(sourcePath, hexDataToReplace, hexDataReplacement); } if (!result && catchErrors) { log("Error in %s command", commandName.c_str()); @@ -700,16 +701,16 @@ int interpretAndExecuteCommand(const std::vector>& comm generateBackup(); } if (!progress.empty()) { - curProgress += 100/commands.size(); + curProgress += 100 / commands.size(); listItem->setValue(std::to_string(curProgress) + "%", tsl::PredefinedColors::Green); //log("q%s", ss.str().c_str()); - } } return 0; } -void MTinterpretAndExecute(void* args){ +void MTinterpretAndExecute(void* args) +{ // Accept pointers to the exit flag and a vector with commands ThreadArgs* threadArgs = static_cast(args); tsl::elm::ListItem* listItem = threadArgs->listItem; @@ -727,7 +728,8 @@ void MTinterpretAndExecute(void* args){ *exitMT = true; } -tsl::PredefinedColors defineColor(const std::string& strColor) { +tsl::PredefinedColors defineColor(const std::string& strColor) +{ // log ("string color: " + strColor); if (strColor == "Green") { return tsl::PredefinedColors::Green; @@ -741,10 +743,11 @@ tsl::PredefinedColors defineColor(const std::string& strColor) { return tsl::PredefinedColors::Gray; } else { return tsl::PredefinedColors::DefaultText; - } + } } -std::pair dispCustData(const std::string& jsonPath, const std::string& kipPath = "/atmosphere/kips/loader.kip", bool spacing = false) { +std::pair dispCustData(const std::string& jsonPath, const std::string& kipPath = "/atmosphere/kips/loader.kip", bool spacing = false) +{ std::string currentHex = ""; std::string extent = ""; @@ -752,7 +755,7 @@ std::pair dispCustData(const std::string& jsonPath, const std: std::string state = ""; std::string name = ""; std::string offsetStr = ""; - std::string increment = ""; + std::string increment = ""; bool allign = false; int checkDefault = 0; size_t length = 0; @@ -828,12 +831,12 @@ std::pair dispCustData(const std::string& jsonPath, const std: } } else { if (keyValue && json_is_string(keyValue)) { - json_t* j_offset = json_object_get(item, "offset"); - json_t* j_length = json_object_get(item, "length"); - json_t* j_extent = json_object_get(item, "extent"); - json_t* j_state = json_object_get(item, "state"); + json_t* j_offset = json_object_get(item, "offset"); + json_t* j_length = json_object_get(item, "length"); + json_t* j_extent = json_object_get(item, "extent"); + json_t* j_state = json_object_get(item, "state"); json_t* j_increment = json_object_get(item, "increment"); - json_t* j_prefix = json_object_get(item, "prefix"); + json_t* j_prefix = json_object_get(item, "prefix"); if (j_state) { state = json_string_value(j_state); @@ -865,8 +868,7 @@ std::pair dispCustData(const std::string& jsonPath, const std: const std::string tempHex = readHexDataAtOffsetF(file, offset, length); // Read the data from kip unsigned int intValue = reversedHexToInt(tempHex); current += std::to_string(intValue) + '-'; - } - catch (const std::invalid_argument& ex) { + } catch (const std::invalid_argument& ex) { log("ERROR - %s:%d - invalid offset value: \"%s\" in \"%s\"", __func__, __LINE__, offsetItem.c_str(), jsonPath.c_str()); } } @@ -912,14 +914,14 @@ std::pair dispCustData(const std::string& jsonPath, const std: intValue += std::stoi(json_string_value(j_increment)); } if (intValue > 10000) { - intValue = intValue/1000; + intValue = intValue / 1000; } if (j_prefix) { - output += name + ": " + json_string_value(j_prefix) + std::to_string(intValue); + output += name + ": " + json_string_value(j_prefix) + std::to_string(intValue); } else { output += name + ": " + std::to_string(intValue); } - if (state == "check_extent" && intValue < 100) + if (state == "check_extent" && intValue < 100) extent = ""; } } @@ -927,7 +929,7 @@ std::pair dispCustData(const std::string& jsonPath, const std: if (!extent.empty()) { output += extent; } - if (state != "no_skip"){ + if (state != "no_skip") { output += '\n'; lineCount++; } else { @@ -952,17 +954,17 @@ std::pair dispCustData(const std::string& jsonPath, const std: return std::make_pair(output, lineCount); } -std::pair dispRAMTmpl(const std::string& dataPath, const std::string& selectedItem) { +std::pair dispRAMTmpl(const std::string& dataPath, const std::string& selectedItem) +{ std::stringstream output; std::string name = ""; - std::string value = ""; + std::string value = ""; int nItems = 0; int lineNum = 0; - if (!isFileOrDirectory(dataPath)) { - return std::make_pair(output.str(), nItems/2); + return std::make_pair(output.str(), nItems / 2); } auto jsonData = readJsonFromFile(dataPath); if (jsonData) { @@ -974,14 +976,15 @@ std::pair dispRAMTmpl(const std::string& dataPath, const std:: if (json_string_value(keyValue) == selectedItem) { output << "These RAM settings will be applied:\n\n\n-------------------------------------------------------------------\n"; - const char *key; - json_t *value; - json_object_foreach(item, key, value) { - int spaces[5] = {4,9,6,6,6}; //TODO: remove hardcode; redo text display processing + const char* key; + json_t* value; + json_object_foreach(item, key, value) + { + int spaces[5] = { 4, 9, 6, 6, 6 }; //TODO: remove hardcode; redo text display processing if (strcmp(key, "name") != 0 && strcmp(key, "t_offsets")) { output << key << ": " << json_string_value(value) << std::string(spaces[lineNum], ' '); nItems++; - if (strlen(key) > 5 && strlen(json_string_value(value))> 1) { + if (strlen(key) > 5 && strlen(json_string_value(value)) > 1) { output << "\n-------------------------------------------------------------------\n"; nItems += 2; } else if (nItems % 2 == 0) { //every second item @@ -994,28 +997,29 @@ std::pair dispRAMTmpl(const std::string& dataPath, const std:: } } } - return std::make_pair(output.str(), nItems/2+5); + return std::make_pair(output.str(), nItems / 2 + 5); } -bool verifyIntegrity (std::string check) { +bool verifyIntegrity(std::string check) +{ bool verified = false; std::transform(check.begin(), check.end(), check.begin(), ::tolower); - + for (size_t i = 0; i < check.length() - 4; ++i) { if (static_cast(check[i]) == 117 && static_cast(check[i + 1]) == 108 && static_cast(check[i + 2]) == 116 && static_cast(check[i + 3]) == 114 && static_cast(check[i + 4]) == 97) { verified = true; - break; + break; } } return verified; } - -void removeLastNumericWord(std::string& str) { +void removeLastNumericWord(std::string& str) +{ // Iterate through the string from the end for (int i = str.length() - 1; i >= 0; --i) { if (str[i] == ' ' && std::isdigit(str[i + 1])) { @@ -1026,7 +1030,8 @@ void removeLastNumericWord(std::string& str) { } } -std::vector parseString(const std::string& str, char delimiter) { +std::vector parseString(const std::string& str, char delimiter) +{ std::vector result; std::istringstream iss(str); std::string token; @@ -1038,7 +1043,8 @@ std::vector parseString(const std::string& str, char delimiter) { return result; } -std::string getVersion(json_t* json) { +std::string getVersion(json_t* json) +{ json_t* error = json_object_get(json, "message"); if (json_string_length(error) != 0) { log("API limit reached"); @@ -1052,9 +1058,10 @@ std::string getVersion(json_t* json) { return "Error"; } -std::string getLinkOnLatest(json_t* json, int dEntry = 1) { +std::string getLinkOnLatest(json_t* json, int dEntry = 1) +{ json_t* assets = json_object_get(json_array_get(json, 0), "assets"); - json_t* link = json_object_get(json_array_get(assets, dEntry-1), "browser_download_url"); + json_t* link = json_object_get(json_array_get(assets, dEntry - 1), "browser_download_url"); if (link && json_is_string(link)) { const std::string linkS = json_string_value(link); return linkS; @@ -1062,8 +1069,8 @@ std::string getLinkOnLatest(json_t* json, int dEntry = 1) { return "Error"; } - -std::map packageUpdateCheck(const std::string& subConfigIniPath) { +std::map packageUpdateCheck(const std::string& subConfigIniPath) +{ std::map packageInfo; PackageHeader packageHeader = getPackageHeaderFromIni(packageDirectory + subConfigIniPath); if (packageHeader.version != "" && packageHeader.github != "") { @@ -1074,7 +1081,7 @@ std::map packageUpdateCheck(const std::string& subConf if (!git_json) { packageInfo.clear(); return packageInfo; - } + } packageInfo["repoVer"] = getVersion(git_json); if (packageInfo["repoVer"] == "ApiLimit" || packageInfo["repoVer"] == "Error") { packageInfo.clear(); @@ -1092,7 +1099,8 @@ std::map packageUpdateCheck(const std::string& subConf return packageInfo; } -std::map ovlUpdateCheck(std::map currentOverlay) { +std::map ovlUpdateCheck(std::map currentOverlay) +{ std::map ovlItemToUpdate; auto git_json = loadJsonFromUrl(currentOverlay["link"]); if (!git_json) { @@ -1106,8 +1114,8 @@ std::map ovlUpdateCheck(std::map