From 6fae77cdc87a49b2504965f6d4e15dc7d02b9b60 Mon Sep 17 00:00:00 2001 From: flb Date: Mon, 28 Dec 2020 19:28:58 +0100 Subject: [PATCH] Added option to change procon color --- LICENSE-THIRD-PARTY | 31 ------ include/PC_color_swapper.hpp | 28 +++++ include/PC_page.hpp | 18 ++++ include/constants.hpp | 1 + include/tools_tab.hpp | 2 + source/PC_color_swapper.cpp | 191 +++++++++++++++++++++++++++++++++++ source/PC_page.cpp | 54 ++++++++++ source/ntcp.cpp | 34 ++++++- source/tools_tab.cpp | 7 ++ 9 files changed, 334 insertions(+), 32 deletions(-) delete mode 100644 LICENSE-THIRD-PARTY create mode 100644 include/PC_color_swapper.hpp create mode 100644 include/PC_page.hpp create mode 100644 source/PC_color_swapper.cpp create mode 100644 source/PC_page.cpp diff --git a/LICENSE-THIRD-PARTY b/LICENSE-THIRD-PARTY deleted file mode 100644 index 3cbeb88..0000000 --- a/LICENSE-THIRD-PARTY +++ /dev/null @@ -1,31 +0,0 @@ -This homebrew uses code from https://github.com/lettier/ntpclient under the following license: - -BSD 3-Clause License - -Copyright (c) 2014, David Lettier -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -* Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/include/PC_color_swapper.hpp b/include/PC_color_swapper.hpp new file mode 100644 index 0000000..d3c5105 --- /dev/null +++ b/include/PC_color_swapper.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "constants.hpp" +#include "progress_event.hpp" +#include "utils.hpp" +#include "json.hpp" + +namespace pc{ +int hexToBGR(std::string hex); +std::string BGRToHex(int v); +bool isHexaAnd3Bytes(std::string str); +int setColor(std::vector colors); +int backupToJSON(nlohmann::json &profiles, const char* path); +void writeJSONToFile(nlohmann::json &profiles, const char* path); +std::tuple, std::vector>> getProfiles(const char* path); +void changePCColor(std::vector values); +nlohmann::json backupProfile(); +void backupPCColor(const char* path); +} \ No newline at end of file diff --git a/include/PC_page.hpp b/include/PC_page.hpp new file mode 100644 index 0000000..587674e --- /dev/null +++ b/include/PC_page.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include "PC_color_swapper.hpp" +#include "confirm_page.hpp" +#include "worker_page.hpp" + +class PCPage : public brls::AppletFrame +{ + private: + brls::List* list; + brls::Label* label; + std::vector items; + brls::ListItem* restore; + brls::ListItem* backup; + + public: + PCPage(); +}; \ No newline at end of file diff --git a/include/constants.hpp b/include/constants.hpp index e589883..75d0a53 100644 --- a/include/constants.hpp +++ b/include/constants.hpp @@ -48,6 +48,7 @@ #define TITLES_PATH "titles/" #define COLOR_PROFILES_PATH "/config/aio-switch-updater/jc_profiles.json" +#define PC_COLOR_PATH "/config/aio-switch-updater/pc_profiles.json" #define PAYLOAD_PATH "/payloads/" #define BOOTLOADER_PATH "/bootloader" diff --git a/include/tools_tab.hpp b/include/tools_tab.hpp index b1727ee..2aca468 100644 --- a/include/tools_tab.hpp +++ b/include/tools_tab.hpp @@ -9,6 +9,7 @@ #include "changelog_page.hpp" #include "language_option_page.hpp" #include "JC_page.hpp" +#include "PC_page.hpp" #include "extract.hpp" #include "utils.hpp" //#include "ntcp.hpp" @@ -18,6 +19,7 @@ class ToolsTab : public brls::List private: brls::ListItem* cheats; brls::ListItem* JCcolor; + brls::ListItem* PCcolor; brls::ListItem* updateApp; brls::ListItem* rebootPayload; brls::ListItem* downloadPayload; diff --git a/source/PC_color_swapper.cpp b/source/PC_color_swapper.cpp new file mode 100644 index 0000000..c793058 --- /dev/null +++ b/source/PC_color_swapper.cpp @@ -0,0 +1,191 @@ +#include "PC_color_swapper.hpp" + +using json = nlohmann::json; + +namespace pc{ +int hexToBGR(std::string hex){ + std::string R = hex.substr(0, 2); + std::string G = hex.substr(2, 2); + std::string B = hex.substr(4, 2); + return std::stoi(B + G + R, 0, 16); +} + +std::string BGRToHex(int v){ + std::stringstream ss; + v = ((v & 0xFF) << 16) + (v & 0xFF00) + (v >> 16) + 256; + ss << std::setfill('0') << std::setw(6) << std::right << std::hex << v; + return ss.str(); +} + +bool isHexaAnd3Bytes(std::string str){ + if(str.size()!=6) return false; + for(char const &c : str){ + if(!isxdigit(c)) return false; + } + return true; +} + +int setColor(std::vector colors){ + Result pads, pc; + int res = 0; + s32 nbEntries; + HidsysUniquePadId UniquePadIds[1] = {}; + + pads = hidsysGetUniquePadsFromNpad(HidNpadIdType_No1, UniquePadIds, 1 ,&nbEntries); + if(R_SUCCEEDED(pads)){ + pc = hiddbgUpdateControllerColor(colors[0], colors[1], UniquePadIds[0]); + if (R_FAILED(pc)) res +=1; + } + else{ + res +=4; + } + return res; +} + +int backupToJSON(json &profiles, const char* path){ + HidNpadControllerColor color; + Result res = hidGetNpadControllerColorSingle(HidNpadIdType_No1, &color); + std::vector oldBackups; + if (R_SUCCEEDED(res)) { + int i = 0; + for (const auto& x : profiles.items()){ + if(x.value()["name"] == "_backup") { + oldBackups.push_back(i); + } + i++; + } + for (auto &k : oldBackups){ + profiles.erase(profiles.begin() + k); + } + json newBackup = json::object({ + {"name", "_backup"}, + {"BODY", BGRToHex(color.main)}, + {"BTN", BGRToHex(color.sub)} + }); + profiles.push_back(newBackup); + writeJSONToFile(profiles, path); + return 0; + } + else{ + return -1; + } +} + +json backupProfile(){ + json newBackup; + HidNpadControllerColor color; + Result res = hidGetNpadControllerColorSingle(HidNpadIdType_No1, &color); + if (R_SUCCEEDED(res)) { + newBackup = json::object({ + {"name", "_backup"}, + {"BODY", BGRToHex(color.main)}, + {"BTN", BGRToHex(color.sub)} + }); + } + return newBackup; + +} + +void writeJSONToFile(json &profiles, const char* path){ + std::fstream newProfiles; + newProfiles.open(path, std::fstream::out | std::fstream::trunc); + newProfiles << std::setw(4) << profiles << std::endl; + newProfiles.close(); +} + +std::tuple, std::vector>> getProfiles(const char* path){ + std::vector names; + std::vector> colorValues; + bool properData; + std::fstream profilesFile; + json profilesJson; + if(std::filesystem::exists(path)){ + profilesFile.open(path, std::fstream::in); + profilesFile >> profilesJson; + profilesFile.close(); + } + if(profilesJson.empty()){ + profilesJson = {{ + {"BTN", "0A1E0A"}, + {"BODY", "82FF96"}, + {"name", "Animal Crossing: New Horizons"} + }}; + writeJSONToFile(profilesJson, path); + } + for (const auto& x : profilesJson.items()){ + std::string name = x.value()["name"]; + std::vector values = { + std::string(x.value()["BODY"]), + std::string(x.value()["BTN"]) + }; + properData = true; + for(auto& str : values){ + if(!isHexaAnd3Bytes(str)){ + properData = false; + } + } + if(properData){ + if(name == "") name = "Unamed"; + names.push_back(name); + colorValues.push_back({ + hexToBGR(values[0]), + hexToBGR(values[1]) + }); + } + } + return std::make_tuple(names, colorValues); +} + +void changePCColor(std::vector values){ + hiddbgInitialize(); + hidsysInitialize(); + ProgressEvent::instance().reset(); + ProgressEvent::instance().setStep(1); + int res = setColor(values); + if(res != 0){ + showDialogBox("Could not change the Joy-Cons color. Make sure they're docked and try again.\nError :" + std::to_string(res), "Ok"); + } + hiddbgExit(); + hidsysExit(); + ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); +} + +void backupPCColor(const char* path){ + hiddbgInitialize(); + hidsysInitialize(); + ProgressEvent::instance().reset(); + ProgressEvent::instance().setStep(1); + json backup; + json profiles; + std::fstream profilesFile; + if(std::filesystem::exists(path)){ + profilesFile.open(path, std::fstream::in); + profilesFile >> profiles; + profilesFile.close(); + } + + std::vector oldBackups; + int i = 0; + for (const auto& x : profiles.items()){ + if(x.value()["name"] == "_backup") { + oldBackups.push_back(i); + } + i++; + } + for (auto &k : oldBackups){ + profiles.erase(profiles.begin() + k); + } + + while(backup.empty()){ + backup = backupProfile(); + } + + profiles.push_back(backup); + //backup.push_back(profiles); + writeJSONToFile(profiles, path); + hiddbgExit(); + hidsysExit(); + ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); +} + +} \ No newline at end of file diff --git a/source/PC_page.cpp b/source/PC_page.cpp new file mode 100644 index 0000000..bf3028d --- /dev/null +++ b/source/PC_page.cpp @@ -0,0 +1,54 @@ +#include "PC_page.hpp" + +namespace i18n = brls::i18n; +using namespace i18n::literals; +PCPage::PCPage() : AppletFrame(true, true) +{ + this->setTitle("menus/joy_con"_i18n ); + list = new brls::List(); + std::string labelText = "menus/jc_you_can_1"_i18n + std::string(PC_COLOR_PATH) + "menus/jc_you_can_goto"\ + "menus/jc_you_can_2"_i18n ; + label = new brls::Label(brls::LabelStyle::DESCRIPTION, labelText, true); + list->addView(label); + + backup = new brls::ListItem("menus/jc_backup"_i18n ); + backup->getClickEvent()->subscribe([&](brls::View* view) { + brls::StagedAppletFrame* stagedFrame = new brls::StagedAppletFrame(); + stagedFrame->setTitle("menus/jc_color"_i18n ); + stagedFrame->addStage( + new WorkerPage(stagedFrame, "menus/jc_backing"_i18n , + [](){pc::backupPCColor(PC_COLOR_PATH);}) + ); + stagedFrame->addStage( + new ConfirmPage(stagedFrame, "menus/jc_all_done"_i18n , true) + ); + brls::Application::pushView(stagedFrame); + }); + list->addView(backup); + + list->addView(new brls::ListItemGroupSpacing(true)); + + auto profiles = pc::getProfiles(PC_COLOR_PATH); + std::vector names = std::get<0>(profiles); + int nbProfiles = names.size(); + items.reserve(nbProfiles); + for (int i = nbProfiles - 1; i >= 0; i--){ + std::string name = std::get<0>(profiles)[i]; + std::vector value = std::get<1>(profiles)[i]; + items[i] = new brls::ListItem(names[i]); + items[i]->getClickEvent()->subscribe([&, value](brls::View* view) { + brls::StagedAppletFrame* stagedFrame = new brls::StagedAppletFrame(); + stagedFrame->setTitle("menus/jc_concolor"_i18n ); + stagedFrame->addStage( + new WorkerPage(stagedFrame, "menus/jc_changing"_i18n , + [value](){pc::changePCColor(value);}) + ); + stagedFrame->addStage( + new ConfirmPage(stagedFrame, "menus/jc_all_"_i18n , true) + ); + brls::Application::pushView(stagedFrame); + }); + list->addView(items[i]); + } + this->setContentView(list); +} \ No newline at end of file diff --git a/source/ntcp.cpp b/source/ntcp.cpp index 97e1f36..c1d4e74 100644 --- a/source/ntcp.cpp +++ b/source/ntcp.cpp @@ -23,7 +23,39 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to -Additionally, the ntp_packet struct uses code licensed under the BSD 3-clause. See LICENSE-THIRD-PARTY for more information. */ +Additionally, the ntp_packet struct uses code licensed under the BSD 3-clause.*/ +/* This homebrew uses code from https://github.com/lettier/ntpclient under the following license: + +BSD 3-Clause License + +Copyright (c) 2014, David Lettier +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ // This code comes from https://github.com/thedax/NX-ntpc, thank you for your work diff --git a/source/tools_tab.cpp b/source/tools_tab.cpp index 134bc5d..3953e0e 100644 --- a/source/tools_tab.cpp +++ b/source/tools_tab.cpp @@ -18,6 +18,13 @@ ToolsTab::ToolsTab(std::string tag) : brls::List() JCcolor->setHeight(LISTITEM_HEIGHT); this->addView(JCcolor); + PCcolor = new brls::ListItem("menus/tool_change_pcrocon"_i18n ); + PCcolor->getClickEvent()->subscribe([&](brls::View* view){ + brls::Application::pushView(new PCPage()); + }); + PCcolor->setHeight(LISTITEM_HEIGHT); + this->addView(PCcolor); + downloadPayload = new brls::ListItem("menus/tool_download"_i18n + std::string(BOOTLOADER_PL_PATH)); downloadPayload->getClickEvent()->subscribe([&](brls::View* view){ brls::Application::pushView(new DownloadPayloadPage());