#include "color_swapper.hpp" #include #include #include #include #include #include "constants.hpp" #include "progress_event.hpp" #include "utils.hpp" #include "fs.hpp" using json = nlohmann::json; namespace ColorSwapper { 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; } } namespace JC { int setColor(std::vector colors){ Result pads, ljc, rjc; int res = 0; s32 nbEntries; HidsysUniquePadId UniquePadIds[2] = {}; pads = hidsysGetUniquePadsFromNpad(HidNpadIdType_Handheld, UniquePadIds, 2,&nbEntries); if(R_SUCCEEDED(pads)){ ljc = hiddbgUpdateControllerColor(colors[0], colors[1], UniquePadIds[0]); if (R_FAILED(ljc)) res +=1; rjc = hiddbgUpdateControllerColor(colors[2], colors[3], UniquePadIds[1]); if (R_FAILED(rjc)) res +=2; } else{ res +=4; } return res; } int backupToJSON(json &profiles, const std::string& path){ HidNpadControllerColor color_left; HidNpadControllerColor color_right; Result res = hidGetNpadControllerColorSplit(HidNpadIdType_Handheld, &color_left, &color_right); 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"}, {"L_JC", ColorSwapper::BGRToHex(color_left.main)}, {"L_BTN", ColorSwapper::BGRToHex(color_left.sub)}, {"R_JC", ColorSwapper::BGRToHex(color_right.main)}, {"R_BTN", ColorSwapper::BGRToHex(color_right.sub)} }); profiles.push_back(newBackup); fs::writeJsonToFile(profiles, path); return 0; } else{ return -1; } } json backupProfile(){ json newBackup; HidNpadControllerColor color_left; HidNpadControllerColor color_right; Result res = hidGetNpadControllerColorSplit(HidNpadIdType_Handheld, &color_left, &color_right); if (R_SUCCEEDED(res)) { newBackup = json::object({ {"name", "_backup"}, {"L_JC", ColorSwapper::BGRToHex(color_left.main)}, {"L_BTN", ColorSwapper::BGRToHex(color_left.sub)}, {"R_JC", ColorSwapper::BGRToHex(color_right.main)}, {"R_BTN", ColorSwapper::BGRToHex(color_right.sub)} }); } return newBackup; } std::vector>> getProfiles(const std::string& path){ std::vector>> res; bool properData; std::fstream profilesFile; json profilesJson = fs::parseJsonFile(path); if(profilesJson.empty()){ profilesJson = {{ {"L_BTN", "0A1E0A"}, {"L_JC", "82FF96"}, {"R_BTN", "0A1E28"}, {"R_JC", "96F5F5"}, {"name", "Animal Crossing: New Horizons"} }}; } for (const auto& x : profilesJson.items()){ std::string name = x.value()["name"]; std::vector values = { std::string(x.value()["L_JC"]), std::string(x.value()["L_BTN"]), std::string(x.value()["R_JC"]), std::string(x.value()["R_BTN"]) }; properData = true; for(auto& str : values){ if(!ColorSwapper::isHexaAnd3Bytes(str)){ properData = false; } } if(properData){ if(name == "") name = "Unamed"; res.push_back(std::make_pair(name, (std::vector){ ColorSwapper::hexToBGR(values[0]), ColorSwapper::hexToBGR(values[1]), ColorSwapper::hexToBGR(values[2]), ColorSwapper::hexToBGR(values[3]) })); } } return res; } void changeJCColor(std::vector values){ hiddbgInitialize(); hidsysInitialize(); ProgressEvent::instance().reset(); ProgressEvent::instance().setStep(1); int res = setColor(values); if(res != 0){ util::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 backupJCColor(const std::string& 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); fs::writeJsonToFile(profiles, path); hiddbgExit(); hidsysExit(); ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); } } namespace PC { 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 std::string& 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", ColorSwapper::BGRToHex(color.main)}, {"BTN", ColorSwapper::BGRToHex(color.sub)} }); profiles.push_back(newBackup); fs::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", ColorSwapper::BGRToHex(color.main)}, {"BTN", ColorSwapper::BGRToHex(color.sub)} }); } return newBackup; } std::vector>> getProfiles(const std::string& path){ std::vector>> res; bool properData; std::fstream profilesFile; json profilesJson = fs::parseJsonFile(path); if(profilesJson.empty()){ profilesJson = {{ {"BTN", "2d2d2d"}, {"BODY", "e6e6e6"}, {"name", "Default black"} }}; } 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(!ColorSwapper::isHexaAnd3Bytes(str)){ properData = false; } } if(properData){ if(name == "") name = "Unamed"; res.push_back(std::make_pair(name, (std::vector){ ColorSwapper::hexToBGR(values[0]), ColorSwapper::hexToBGR(values[1]) })); } } return res; } void changePCColor(std::vector values){ hiddbgInitialize(); hidsysInitialize(); ProgressEvent::instance().reset(); ProgressEvent::instance().setStep(1); int res = setColor(values); if(res != 0){ util::showDialogBox("Could not change the Pro-Con color. Make they're connected to P1. This feature may not work on unoffical controllers. \nError :" + std::to_string(res), "Ok"); } hiddbgExit(); hidsysExit(); ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); } void backupPCColor(const std::string& 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); fs::writeJsonToFile(profiles, path); hiddbgExit(); hidsysExit(); ProgressEvent::instance().setStep(ProgressEvent::instance().getMax()); } }