mirror of
https://github.com/HamletDuFromage/aio-switch-updater.git
synced 2024-12-29 10:56:01 +00:00
Added option to change procon color
This commit is contained in:
parent
dd19949328
commit
6fae77cdc8
9 changed files with 334 additions and 32 deletions
|
@ -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.
|
28
include/PC_color_swapper.hpp
Normal file
28
include/PC_color_swapper.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <tuple>
|
||||
|
||||
#include <switch.h>
|
||||
#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<int> colors);
|
||||
int backupToJSON(nlohmann::json &profiles, const char* path);
|
||||
void writeJSONToFile(nlohmann::json &profiles, const char* path);
|
||||
std::tuple<std::vector<std::string>, std::vector<std::vector<int>>> getProfiles(const char* path);
|
||||
void changePCColor(std::vector<int> values);
|
||||
nlohmann::json backupProfile();
|
||||
void backupPCColor(const char* path);
|
||||
}
|
18
include/PC_page.hpp
Normal file
18
include/PC_page.hpp
Normal file
|
@ -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<brls::ListItem*> items;
|
||||
brls::ListItem* restore;
|
||||
brls::ListItem* backup;
|
||||
|
||||
public:
|
||||
PCPage();
|
||||
};
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
|
191
source/PC_color_swapper.cpp
Normal file
191
source/PC_color_swapper.cpp
Normal file
|
@ -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<int> 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<int> 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<std::string>, std::vector<std::vector<int>>> getProfiles(const char* path){
|
||||
std::vector<std::string> names;
|
||||
std::vector<std::vector<int>> 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<std::string> 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<int> 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<int> 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());
|
||||
}
|
||||
|
||||
}
|
54
source/PC_page.cpp
Normal file
54
source/PC_page.cpp
Normal file
|
@ -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<std::string> 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<int> 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);
|
||||
}
|
|
@ -23,7 +23,39 @@ OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
For more information, please refer to <http://unlicense.org>
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
Loading…
Reference in a new issue