This commit is contained in:
hanai3Bi
2023-04-01 01:49:31 +03:00
committed by hanabbi
parent 63bbde2f58
commit 3db0b9b380
210 changed files with 1286 additions and 48394 deletions

View File

@@ -1,64 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019-2020 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "about_tab.h"
#include "logo.h"
#include "ipc/ipc.h"
#include "ipc/client.h"
#include <borealis.hpp>
AboutTab::AboutTab()
{
this->addView(new Logo(LogoStyle::ABOUT));
// Subtitle
brls::Label *subTitle = new brls::Label(
brls::LabelStyle::REGULAR,
"This is a modified version of official sys-clk, which is not associated with any author below.\n" \
"Nintendo Switch overclocking / underclocking system module and frontend app by the RetroNX Team.\n",
true
);
subTitle->setHorizontalAlign(NVG_ALIGN_CENTER);
this->addView(subTitle);
// Copyright
brls::Label *copyright = new brls::Label(
brls::LabelStyle::DESCRIPTION,
"System module licensed under the Beerware license\n" \
"Frontend app licensed under GPL-3.0\n" \
"\u00A9 2019 - 2020 natinusala, p-sam, m4xw",
true
);
copyright->setHorizontalAlign(NVG_ALIGN_CENTER);
this->addView(copyright);
// Links
this->addView(new brls::Header("Links and Resources"));
brls::Label *links = new brls::Label(
brls::LabelStyle::SMALL,
"\uE016 User guide and code source can be found on our GitHub repository\n" \
"\uE016 The sys-clk manager is powered by Borealis, an hardware accelerated UI library\n" \
"\uE016 Join the RetroNX Discord server for support, to request features or just hang out!",
true
);
this->addView(links);
}

View File

@@ -1,34 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019-2020 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
class AboutTab : public brls::List
{
public:
AboutTab();
View* getDefaultFocus() override
{
return nullptr;
}
};

View File

@@ -1,192 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "advanced_settings_tab.h"
#include "app_profile_frame.h"
#include "utils.h"
#include <sysclk/clocks.h>
AdvancedSettingsTab::AdvancedSettingsTab()
{
// Get context
SysClkContext context;
Result rc = sysclkIpcGetCurrentContext(&context);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to get context");
errorResult("sysclkIpcGetCurrentContext", rc);
brls::Application::crash("Could not get the current sys-clk context, please check that it is correctly installed and enabled.");
return;
}
// Create UI
// Disclaimer
this->addView(new brls::Label(brls::LabelStyle::REGULAR, "\uE140 Please only alter these settings if you know what you are doing.", true));
// Temporary overrides
this->addView(new brls::Header("Temporary overrides"));
// CPU
brls::SelectListItem *cpuFreqListItem = createFreqListItem(SysClkModule_CPU, context.overrideFreqs[SysClkModule_CPU] / 1000000);
cpuFreqListItem->getValueSelectedEvent()->subscribe([](int result){
Result rc = result == 0 ?
sysclkIpcRemoveOverride(SysClkModule_CPU) :
sysclkIpcSetOverride(SysClkModule_CPU, g_freq_table_cpu_hz[result - 1]);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to update CPU Override");
errorResult(result == 0 ? "sysclkIpcRemoveOverride" : "sysclkIpcSetOverride", rc);
// TODO: Reset selected value
}
});
// GPU
brls::SelectListItem *gpuFreqListItem = createFreqListItem(SysClkModule_GPU, context.overrideFreqs[SysClkModule_GPU] / 1000000);
gpuFreqListItem->getValueSelectedEvent()->subscribe([](int result){
Result rc = result == 0 ?
sysclkIpcRemoveOverride(SysClkModule_GPU) :
sysclkIpcSetOverride(SysClkModule_GPU, g_freq_table_gpu_hz[result - 1]);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to update GPU Override");
errorResult(result == 0 ? "sysclkIpcRemoveOverride" : "sysclkIpcSetOverride", rc);
// TODO: Reset selected value
}
});
// MEM
brls::SelectListItem *memFreqListItem = createFreqListItem(SysClkModule_MEM, context.overrideFreqs[SysClkModule_MEM] / 1000000);
memFreqListItem->getValueSelectedEvent()->subscribe([](int result)
{
Result rc = result == 0 ?
sysclkIpcRemoveOverride(SysClkModule_MEM) :
sysclkIpcSetOverride(SysClkModule_MEM, g_freq_table_mem_hz[result - 1]);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to update MEM Override");
errorResult(result == 0 ? "sysclkIpcRemoveOverride" : "sysclkIpcSetOverride", rc);
// TODO: Reset selected value
}
});
this->addView(cpuFreqListItem);
this->addView(gpuFreqListItem);
this->addView(memFreqListItem);
// Global profile
this->addView(new brls::Header("Global profile"));
// Add the ListItem to Global profile
Title* globalTitle = (Title*) malloc(sizeof(Title));
globalTitle->tid = SYSCLK_GLOBAL_PROFILE_TID;
brls::ListItem *globalList = new brls::ListItem(std::string("Set global profile"));
globalList->getClickEvent()->subscribe([globalTitle](View* view) {
AppProfileFrame* profileFrame = new AppProfileFrame(globalTitle);
brls::Application::pushView(profileFrame, brls::ViewAnimation::SLIDE_LEFT);
});
this->addView(globalList);
// Config
// Broken, only accepting single digit
// this->addView(new brls::Header("Configuration"));
// Logging
// TODO: add a logger view and put the button to enter it here
// Config entries
// TODO: add constraints to the swkbd if possible (min / max)
// sysclkIpcGetConfigValues(&this->configValues);
// for (int i = 0; i < SysClkConfigValue_EnumMax; i++)
// {
// SysClkConfigValue config = (SysClkConfigValue) i;
// std::string label = std::string(sysclkFormatConfigValue(config, true));
// std::string description = this->getDescriptionForConfig(config);
// uint64_t defaultValue = configValues.values[config];
// brls::IntegerInputListItem* configItem = new brls::IntegerInputListItem(label, defaultValue, label, description);
// configItem->setReduceDescriptionSpacing(true);
// configItem->getClickEvent()->subscribe([this, configItem, config](View* view)
// {
// try
// {
// int value = std::stoi(configItem->getValue());
// // Validate the value
// if (value < 0)
// {
// brls::Application::notify("\uE5CD Couldn't save configuration: invalid value (is negative)");
// configItem->setValue(std::to_string(this->configValues.values[config]));
// return;
// }
// uint64_t uvalue = (uint64_t) value;
// if (!sysclkValidConfigValue(config, uvalue))
// {
// brls::Application::notify("\uE5CD Couldn't save configuration: invalid value");
// configItem->setValue(std::to_string(this->configValues.values[config]));
// return;
// }
// // Save the config
// this->configValues.values[config] = uvalue;
// sysclkIpcSetConfigValues(&this->configValues);
// brls::Application::notify("\uE14B Configuration saved");
// }
// catch(const std::exception& e)
// {
// brls::Logger::error("Unable to parse config value %s: %s", configItem->getValue().c_str(), e.what());
// }
// });
// this->addView(configItem);
// }
}
std::string AdvancedSettingsTab::getDescriptionForConfig(SysClkConfigValue config)
{
switch (config)
{
case SysClkConfigValue_CsvWriteIntervalMs:
return "How often to update /config/sys-clk/context.csv (in milliseconds)\n\uE016 Use 0 to disable";
case SysClkConfigValue_TempLogIntervalMs:
return "How often to log temperatures (in milliseconds)\n\uE016 Use 0 to disable";
case SysClkConfigValue_PollingIntervalMs:
return "How fast to check and apply profiles (in milliseconds)";
default:
return "";
}
}

View File

@@ -1,39 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "ipc/client.h"
class AdvancedSettingsTab : public brls::List
{
public:
AdvancedSettingsTab();
private:
std::string getDescriptionForConfig(SysClkConfigValue config);
bool isLoggingEnabled();
void setLoggingEnabled(bool value);
SysClkConfigValueList configValues;
};

View File

@@ -1,171 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "app_profile_frame.h"
#include <borealis.hpp>
#include "utils.h"
#include "ipc/client.h"
#include <cstring>
AppProfileFrame::AppProfileFrame(Title* title) : ThumbnailFrame(), title(title)
{
bool isGlobal = (title->tid == SYSCLK_GLOBAL_PROFILE_TID);
this->setTitle(isGlobal ? "Edit global profile" : "Edit application profile");
this->setIcon(new brls::MaterialIcon("\uE315"));
// Get the freqs
Result rc = sysclkIpcGetProfiles(title->tid, &this->profiles);
if (R_FAILED(rc))
errorResult("sysclkIpcGetProfiles", rc);
// Setup the right sidebar
if (!isGlobal)
{
this->getSidebar()->setThumbnail(title->icon, sizeof(title->icon));
this->getSidebar()->setTitle(std::string(title->name));
this->getSidebar()->setSubtitle(formatTid(title->tid));
}
this->getSidebar()->getButton()->setState(brls::ButtonState::DISABLED);
this->getSidebar()->getButton()->getClickEvent()->subscribe([this, title](brls::View* view)
{
SysClkTitleProfileList profiles;
memcpy(&profiles, &this->profiles, sizeof(SysClkTitleProfileList));
for (int p = 0; p < SysClkProfile_EnumMax; p++)
{
for (int m = 0; m < SysClkModule_EnumMax; m++)
profiles.mhzMap[p][m] /= 1000000;
}
Result rc = sysclkIpcSetProfiles(title->tid, &profiles);
if (R_SUCCEEDED(rc))
{
// TODO: set the tick mark color to blue/green once borealis has rich text support
brls::Application::notify("\uE14B Profile saved");
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
}
else
{
errorResult("sysclkIpcSetProfiles", rc);
brls::Application::notify("An error occured while saving the profile - see logs for more details");
}
});
// Setup the list
brls::List* list = new brls::List();
this->addFreqs(list, SysClkProfile_Docked);
this->addFreqs(list, SysClkProfile_Handheld);
this->addFreqs(list, SysClkProfile_HandheldCharging);
this->addFreqs(list, SysClkProfile_HandheldChargingOfficial);
this->addFreqs(list, SysClkProfile_HandheldChargingUSB);
this->setContentView(list);
}
void AppProfileFrame::addFreqs(brls::List* list, SysClkProfile profile)
{
// Get the freqs
list->addView(new brls::Header(std::string(sysclkFormatProfile(profile, true))));
// CPU
brls::SelectListItem* cpuListItem = createFreqListItem(SysClkModule_CPU, this->profiles.mhzMap[profile][SysClkModule_CPU]);
this->profiles.mhzMap[profile][SysClkModule_CPU] *= 1000000;
cpuListItem->getValueSelectedEvent()->subscribe([this, profile](int result) {
this->onProfileChanged();
this->profiles.mhzMap[profile][SysClkModule_CPU] = result == 0 ? result : g_freq_table_cpu_hz[result - 1];
brls::Logger::debug("Caching freq for module %d and profile %d to %" PRIu32, SysClkModule_CPU, profile, this->profiles.mhzMap[profile][SysClkModule_CPU]);
});
list->addView(cpuListItem);
// GPU
brls::SelectListItem* gpuListItem = createFreqListItem(SysClkModule_GPU, this->profiles.mhzMap[profile][SysClkModule_GPU]);
this->profiles.mhzMap[profile][SysClkModule_GPU] *= 1000000;
gpuListItem->getValueSelectedEvent()->subscribe([this, profile](int result) {
this->onProfileChanged();
this->profiles.mhzMap[profile][SysClkModule_GPU] = result == 0 ? result : g_freq_table_gpu_hz[result - 1];
brls::Logger::debug("Caching freq for module %d and profile %d to %" PRIu32, SysClkModule_GPU, profile, this->profiles.mhzMap[profile][SysClkModule_GPU]);
});
list->addView(gpuListItem);
// MEM
brls::SelectListItem* memListItem = createFreqListItem(SysClkModule_MEM, this->profiles.mhzMap[profile][SysClkModule_MEM]);
this->profiles.mhzMap[profile][SysClkModule_MEM] *= 1000000;
memListItem->getValueSelectedEvent()->subscribe([this, profile](int result) {
this->onProfileChanged();
this->profiles.mhzMap[profile][SysClkModule_MEM] = result == 0 ? result : g_freq_table_mem_hz[result - 1];
brls::Logger::debug("Caching freq for module %d and profile %d to %" PRIu32, SysClkModule_MEM, profile, this->profiles.mhzMap[profile][SysClkModule_MEM]);
});
list->addView(memListItem);
}
void AppProfileFrame::onProfileChanged()
{
this->getSidebar()->getButton()->setState(brls::ButtonState::ENABLED);
this->updateActionHint(brls::Key::B, "Cancel");
}
bool AppProfileFrame::onCancel()
{
if (this->hasProfileChanged())
{
brls::Dialog* dialog = new brls::Dialog("You have unsaved changes to this profile!\nAre you sure you want to discard them?");
dialog->addButton("No", [dialog](brls::View* view){
dialog->close();
});
dialog->addButton("Yes", [dialog](brls::View* view){
dialog->close([](){
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
});
});
dialog->open();
}
else
{
brls::Application::popView(brls::ViewAnimation::SLIDE_RIGHT);
}
return true;
}
bool AppProfileFrame::hasProfileChanged()
{
return this->getSidebar()->getButton()->getState() == brls::ButtonState::ENABLED;
}

View File

@@ -1,46 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include <sysclk/clocks.h>
#include "app_profiles_tab.h"
class AppProfileFrame : public brls::ThumbnailFrame
{
public:
AppProfileFrame(Title* title);
bool onCancel() override;
private:
Title* title;
SysClkTitleProfileList profiles;
bool hasProfileChanged();
void addFreqs(brls::List* list, SysClkProfile profile);
void onProfileChanged();
};

View File

@@ -1,244 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "app_profiles_tab.h"
#include "app_profile_frame.h"
#include "ipc/client.h"
#include "ipc/ipc.h"
#include <cstring>
#include "utils.h"
#define PROFILE_BADGE "\uE3E0"
AppProfilesTab::AppProfilesTab()
{
// Filter toggle
this->filterListItem = new brls::ToggleListItem("Show applications with no profile", this->showEmptyProfiles, "", "Yes", "No");
filterListItem->getClickEvent()->subscribe([this](View* v)
{
this->refreshFilter();
});
this->addView(filterListItem);
// Spacing
this->addView(new brls::ListItemGroupSpacing());
// Applications list
NsApplicationRecord record;
uint64_t tid;
NsApplicationControlData controlData;
NacpLanguageEntry* langEntry = NULL;
Result rc;
size_t i = 0;
int recordCount = 0;
size_t controlSize = 0;
while (true)
{
// Record
rc = nsListApplicationRecord(&record, sizeof(record), i, &recordCount);
if (R_FAILED(rc))
{
errorResult("nsListApplicationRecord", rc);
break;
}
if(recordCount <= 0)
break;
tid = record.application_id;
// Control data
rc = nsGetApplicationControlData(NsApplicationControlSource_Storage, tid, &controlData, sizeof(controlData), &controlSize);
if (R_FAILED(rc))
{
errorResult("nsGetApplicationControlData", rc);
break;
}
// Language entry
rc = nacpGetLanguageEntry(&controlData.nacp, &langEntry);
if (R_FAILED(rc))
{
errorResult("nacpGetLanguageEntry", rc);
break;
}
// Name
if (!langEntry->name)
{
i++;
continue;
}
Title* title = (Title*) malloc(sizeof(Title));
title->tid = tid;
memset(title->name, 0, sizeof(title->name));
strncpy(title->name, langEntry->name, sizeof(title->name)-1);
memcpy(title->icon, controlData.icon, sizeof(title->icon));
// Profile
rc = sysclkIpcGetProfileCount(tid, &title->profileCount);
if (R_FAILED(rc))
{
errorResult("sysclkIpcGetProfileCount", rc);
free(title);
break;
}
// Add the ListItem
brls::ListItem *listItem = new brls::ListItem(formatListItemTitle(std::string(title->name)), "", formatTid(title->tid));
title->listItem = listItem;
this->items.push_back(listItem);
if (title->profileCount > 0)
{
listItem->setValue(PROFILE_BADGE);
this->profilesItems.push_back(listItem);
}
else
{
this->emptyProfilesItems.push_back(listItem);
if (!this->showEmptyProfiles)
listItem->collapse(false);
}
listItem->setThumbnail(title->icon, sizeof(title->icon));
listItem->getClickEvent()->subscribe([this, title](View* view) {
this->editingTitle = title;
AppProfileFrame* profileFrame = new AppProfileFrame(title);
brls::Application::pushView(profileFrame, brls::ViewAnimation::SLIDE_LEFT);
});
this->addView(listItem);
this->titles.push_back(title);
i++;
}
// Empty list message
this->emptyListLabel = new brls::Label(brls::LabelStyle::REGULAR, "", true);
this->addView(emptyListLabel);
this->updateEmptyListLabel(false);
}
void AppProfilesTab::updateEmptyListLabel(bool animate)
{
if (this->items.empty())
{
this->emptyListLabel->setText("\uE140 You don't have any application installed on your Nintendo Switch.");
this->emptyListLabel->show([](){}, animate);
}
else if (!this->showEmptyProfiles && this->profilesItems.empty())
{
this->emptyListLabel->setText("\uE140 You don't have any application with a defined profile at the moment.");
this->emptyListLabel->show([](){}, animate);
}
else
{
this->emptyListLabel->hide([](){}, animate);
}
}
AppProfilesTab::~AppProfilesTab()
{
for (Title* title : this->titles)
free(title);
this->titles.clear();
}
void AppProfilesTab::willAppear(bool resetState)
{
if (this->editingTitle != nullptr)
{
bool hadProfiles = this->editingTitle->profileCount > 0;
Result rc = sysclkIpcGetProfileCount(this->editingTitle->tid, &this->editingTitle->profileCount);
bool hasProfiles = this->editingTitle->profileCount > 0;
if (R_FAILED(rc))
{
errorResult("sysclkIpcGetProfileCount", rc);
this->editingTitle = nullptr;
return;
}
// Update the profile badge
if (hasProfiles)
this->editingTitle->listItem->setValue(PROFILE_BADGE);
else
this->editingTitle->listItem->setValue("");
// Update lists
// Remove from emptyProfilesItems if it didn't have a profile
// but has one now
// Add to profilesItems
if (!hadProfiles && hasProfiles)
{
this->emptyProfilesItems.erase(std::remove(this->emptyProfilesItems.begin(), this->emptyProfilesItems.end(), this->editingTitle->listItem), this->emptyProfilesItems.end());
this->profilesItems.push_back(this->editingTitle->listItem);
}
// Add to emptyProfilesItems if it had a profile but doesn't
// has one now
// Remove from profilesItems
if (hadProfiles && !hasProfiles)
{
this->emptyProfilesItems.push_back(this->editingTitle->listItem);
this->profilesItems.erase(std::remove(this->profilesItems.begin(), this->profilesItems.end(), this->editingTitle->listItem), this->profilesItems.end());
}
// Refresh the filter
this->refreshFilter();
// Cleanup
this->editingTitle = nullptr;
}
}
void AppProfilesTab::refreshFilter()
{
this->showEmptyProfiles = this->filterListItem->getToggleState();
for (brls::ListItem *listItem : this->emptyProfilesItems)
{
if (this->showEmptyProfiles)
listItem->expand();
else
listItem->collapse();
this->updateEmptyListLabel();
}
}

View File

@@ -1,62 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "ipc/ipc.h"
typedef struct
{
uint64_t tid;
NsApplicationName name;
NsApplicationIcon icon;
uint8_t profileCount;
brls::ListItem* listItem;
} Title;
class AppProfilesTab : public brls::List
{
private:
bool showEmptyProfiles = true;
std::vector<Title*> titles;
std::vector<brls::ListItem*> items;
std::vector<brls::ListItem*> emptyProfilesItems;
std::vector<brls::ListItem*> profilesItems;
brls::Label *emptyListLabel;
brls::ToggleListItem *filterListItem;
void updateEmptyListLabel(bool animate = true);
Title* editingTitle = nullptr;
void refreshFilter();
public:
AppProfilesTab();
~AppProfilesTab();
void willAppear(bool resetState) override;
};

View File

@@ -1,78 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019-2020 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "cheat_sheet_tab.h"
#include "ipc/client.h"
#include "utils.h"
#include <borealis.hpp>
CheatSheetTab::CheatSheetTab()
{
// CPU
this->addView(new brls::Header("CPU Clocks"));
brls::Table *cpuTable = new brls::Table();
cpuTable->addRow(brls::TableRowType::BODY, "Tegra X1+ Official Max", "1963.5 MHz");
cpuTable->addRow(brls::TableRowType::BODY, "Official Boost", "1785.0 MHz");
cpuTable->addRow(brls::TableRowType::BODY, "Official Docked and Handheld", "1020.0 MHz");
this->addView(cpuTable);
// GPU
this->addView(new brls::Header("GPU Clocks"));
brls::Table *gpuTable = new brls::Table();
gpuTable->addRow(brls::TableRowType::BODY, "Tegra X1+ Official Max", "1267.2 MHz");
gpuTable->addRow(brls::TableRowType::BODY, "Official Maximum", "921.6 MHz");
gpuTable->addRow(brls::TableRowType::BODY, "Official Docked", "768.0 MHz");
gpuTable->addRow(brls::TableRowType::BODY, "Official Handheld", "384.0/460.8 MHz");
this->addView(gpuTable);
// MEM
this->addView(new brls::Header("MEM Clocks"));
brls::Table *memTable = new brls::Table();
// Get context
SysClkContext context;
Result rc = sysclkIpcGetCurrentContext(&context);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to get context");
errorResult("sysclkIpcGetCurrentContext", rc);
brls::Application::crash("Could not get the current sys-clk context, please check that it is correctly installed and enabled.");
return;
}
memTable->addRow(brls::TableRowType::BODY, "Tegra X1+ Official Max", "2131.2 MHz");
memTable->addRow(brls::TableRowType::BODY, "Official", "1331.2/1600.0 MHz");
this->addView(memTable);
}
void CheatSheetTab::customSpacing(brls::View* current, brls::View* next, int* spacing)
{
if (dynamic_cast<brls::Table*>(current))
*spacing = 0;
else
List::customSpacing(current, next, spacing);
}

View File

@@ -1,38 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019-2020 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
class CheatSheetTab : public brls::List
{
public:
bool isMariko = false;
CheatSheetTab();
void customSpacing(brls::View* current, brls::View* next, int* spacing) override;
View* getDefaultFocus() override
{
return nullptr;
}
};

View File

@@ -1,26 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "ipc.h"
#include <sysclk.h>
#include <sysclk/client/ipc.h>

View File

@@ -1,43 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#ifdef __SWITCH__
#ifdef __cplusplus
extern "C" {
#endif
#include <switch.h>
#ifdef __cplusplus
}
#endif
#else
#include "pc_shim/nacp.h"
#include "pc_shim/ns.h"
#include "pc_shim/types.h"
#endif

View File

@@ -1,313 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "client.h"
#include <string.h>
#include <stdlib.h>
static SysClkShimServer* g_server = NULL;
bool sysclkIpcRunning()
{
return true;
}
Result sysclkIpcInitialize()
{
if(!g_server)
{
g_server = new SysClkShimServer();
g_server->SetContextApplicationId(0x0100000000001000ULL);
g_server->SetContextHz(SysClkModule_CPU, 1020000000);
g_server->SetContextHz(SysClkModule_GPU, 307200000);
g_server->SetContextHz(SysClkModule_MEM, 1065600000);
g_server->SetContextTemp(SysClkThermalSensor_PCB, 45700);
g_server->SetContextTemp(SysClkThermalSensor_SOC, 48200);
g_server->SetContextEnabled(true);
g_server->SetProfile(0x010000000000F002, SysClkModule_CPU, SysClkProfile_Docked, 1224);
g_server->SetProfile(0x010000000000F002, SysClkModule_GPU, SysClkProfile_Docked, 921);
g_server->SetProfile(0x010000000000F002, SysClkModule_MEM, SysClkProfile_Docked, 1600);
g_server->SetProfile(0x010000000000F002, SysClkModule_CPU, SysClkProfile_Handheld, 1224);
g_server->SetProfile(0x010000000000F002, SysClkModule_MEM, SysClkProfile_Handheld, 1600);
g_server->SetConfigValue(SysClkConfigValue_CsvWriteIntervalMs, 5000);
}
return 0;
}
void sysclkIpcExit()
{
if(g_server)
delete g_server;
}
Result sysclkIpcGetAPIVersion(u32* out_ver)
{
*out_ver = SYSCLK_IPC_API_VERSION;
return 0;
}
Result sysclkIpcGetVersionString(char* out, size_t len)
{
strncpy(out, "- shim server -", len-1);
return 0;
}
Result sysclkIpcGetCurrentContext(SysClkContext* out_context)
{
g_server->CopyContext(out_context);
return 0;
}
Result sysclkIpcGetProfileCount(u64 tid, u8* out_count)
{
*out_count = g_server->CountProfiles(tid);
return 0;
}
Result sysclkIpcGetProfiles(u64 tid, SysClkTitleProfileList* out_profiles)
{
g_server->GetProfiles(tid, out_profiles);
return 0;
}
Result sysclkIpcSetProfiles(u64 tid, SysClkTitleProfileList* profiles)
{
g_server->SetProfiles(tid, profiles);
return 0;
}
Result sysclkIpcSetEnabled(bool enabled)
{
g_server->SetContextEnabled(enabled);
if(enabled)
{
g_server->SetContextTemp(SysClkThermalSensor_PCB, 45700);
g_server->SetContextTemp(SysClkThermalSensor_SOC, 48200);
}
else
{
g_server->SetContextTemp(SysClkThermalSensor_PCB, 34200);
g_server->SetContextTemp(SysClkThermalSensor_SOC, 42800);
}
return 0;
}
Result sysclkIpcExitCmd()
{
return 0;
}
Result sysclkIpcSetOverride(SysClkModule module, u32 hz)
{
g_server->SetContextOverride(module, hz);
return 0;
}
Result sysclkIpcGetConfigValues(SysClkConfigValueList* out_configValues)
{
g_server->GetConfigValues(out_configValues);
return 0;
}
Result sysclkIpcSetConfigValues(SysClkConfigValueList* configValues)
{
g_server->SetConfigValues(configValues);
return 0;
}
SysClkShimServer::SysClkShimServer()
{
this->store = std::map<std::tuple<u64, SysClkModule, SysClkProfile>, u32>();
this->SetContextApplicationId(0);
this->SetContextHz(SysClkModule_CPU, 0);
this->SetContextHz(SysClkModule_GPU, 0);
this->SetContextHz(SysClkModule_MEM, 0);
this->SetContextOverride(SysClkModule_CPU, 0);
this->SetContextOverride(SysClkModule_GPU, 0);
this->SetContextOverride(SysClkModule_MEM, 0);
this->SetContextTemp(SysClkThermalSensor_PCB, 0);
this->SetContextTemp(SysClkThermalSensor_SOC, 0);
this->SetContextProfile(SysClkProfile_Handheld);
this->SetContextEnabled(false);
for(int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
{
this->configValues[kval] = sysclkDefaultConfigValue((SysClkConfigValue)kval);
}
}
void SysClkShimServer::SetContextApplicationId(u64 tid)
{
this->context.applicationId = tid;
}
void SysClkShimServer::SetContextHz(SysClkModule module, u32 hz)
{
if(module < SysClkModule_EnumMax)
{
this->context.freqs[module] = hz;
}
}
void SysClkShimServer::SetContextTemp(SysClkThermalSensor sensor, u32 temp)
{
if(sensor < SysClkThermalSensor_EnumMax)
{
this->context.temps[sensor] = temp;
}
}
void SysClkShimServer::CopyContext(SysClkContext* out_context)
{
memcpy(out_context, &this->context, sizeof(SysClkContext));
}
void SysClkShimServer::SetContextProfile(SysClkProfile profile)
{
if(profile < SysClkProfile_EnumMax)
{
this->context.profile = profile;
}
}
void SysClkShimServer::SetContextEnabled(bool enabled)
{
this->context.enabled = enabled;
}
void SysClkShimServer::SetProfile(uint64_t applicationId, SysClkModule module, SysClkProfile profile, u32 mhz)
{
std::tuple<u64, SysClkModule, SysClkProfile> key = std::make_tuple(applicationId, module, profile);
if(mhz > 0)
{
this->store[key] = mhz;
}
else
{
this->store.erase(key);
}
}
u32 SysClkShimServer::GetProfileMhz(uint64_t applicationId, SysClkModule module, SysClkProfile profile)
{
std::tuple<u64, SysClkModule, SysClkProfile> key = std::make_tuple(applicationId, module, profile);
std::map<std::tuple<u64, SysClkModule, SysClkProfile>, u32>::iterator it = this->store.find(key);
if(it != this->store.end())
{
return it->second;
}
return 0;
}
void SysClkShimServer::GetProfiles(u64 applicationId, SysClkTitleProfileList* out_profiles)
{
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
{
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
{
out_profiles->mhzMap[profile][module] = this->GetProfileMhz(applicationId, (SysClkModule)module, (SysClkProfile)profile);
}
}
}
void SysClkShimServer::SetProfiles(u64 applicationId, SysClkTitleProfileList* profiles)
{
for(unsigned int profile = 0; profile < SysClkProfile_EnumMax; profile++)
{
for(unsigned int module = 0; module < SysClkModule_EnumMax; module++)
{
this->SetProfile(applicationId, (SysClkModule)module, (SysClkProfile)profile, profiles->mhzMap[profile][module]);
}
}
}
u8 SysClkShimServer::CountProfiles(u64 applicationId)
{
return std::accumulate(
std::begin(this->store),
std::end(this->store),
0,
[applicationId] (u8 value, const std::map<std::tuple<u64, SysClkModule, SysClkProfile>, u32>::value_type& p)
{
if(std::get<0>(p.first) == applicationId)
{
value++;
}
return value;
}
);
}
void SysClkShimServer::SetContextOverride(SysClkModule module, u32 hz)
{
if(SYSCLK_ENUM_VALID(SysClkModule, module))
{
this->context.overrideFreqs[module] = hz;
}
}
u64 SysClkShimServer::GetConfigValue(SysClkConfigValue kval)
{
if(SYSCLK_ENUM_VALID(SysClkConfigValue, kval))
{
return this->configValues[kval];
}
return 0;
}
void SysClkShimServer::SetConfigValue(SysClkConfigValue kval, u64 val)
{
if(SYSCLK_ENUM_VALID(SysClkConfigValue, kval))
{
if(sysclkValidConfigValue(kval, this->configValues[kval]))
{
this->configValues[kval] = val;
}
else
{
this->configValues[kval] = sysclkDefaultConfigValue(kval);
}
}
}
void SysClkShimServer::GetConfigValues(SysClkConfigValueList* out_configValues)
{
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
{
out_configValues->values[kval] = this->GetConfigValue((SysClkConfigValue)kval);
}
}
void SysClkShimServer::SetConfigValues(SysClkConfigValueList* configValues)
{
for(unsigned int kval = 0; kval < SysClkConfigValue_EnumMax; kval++)
{
this->SetConfigValue((SysClkConfigValue)kval, configValues->values[kval]);
}
}

View File

@@ -1,52 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <numeric>
#include "../client.h"
class SysClkShimServer
{
public:
SysClkShimServer();
void SetContextApplicationId(u64 tid);
void SetContextHz(SysClkModule module, u32 hz);
void SetContextTemp(SysClkThermalSensor sensor, u32 temp);
void SetContextProfile(SysClkProfile profile);
void SetContextEnabled(bool enabled);
void SetContextOverride(SysClkModule module, u32 hz);
void CopyContext(SysClkContext* out_context);
void SetProfile(uint64_t applicationId, SysClkModule module, SysClkProfile profile, u32 mhz);
u32 GetProfileMhz(uint64_t applicationId, SysClkModule module, SysClkProfile profile);
void GetProfiles(u64 applicationId, SysClkTitleProfileList* out_profiles);
void SetProfiles(u64 applicationId, SysClkTitleProfileList* profiles);
u8 CountProfiles(u64 applicationId);
u64 GetConfigValue(SysClkConfigValue kval);
void SetConfigValue(SysClkConfigValue kval, u64 val);
void GetConfigValues(SysClkConfigValueList* out_configValues);
void SetConfigValues(SysClkConfigValueList* configValues);
protected:
SysClkContext context;
std::map<std::tuple<u64, SysClkModule, SysClkProfile>, u32> store;
u64 configValues[SysClkConfigValue_EnumMax];
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -1,44 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
typedef struct
{
char name[0x200];
} NacpLanguageEntry;
typedef struct
{
NacpLanguageEntry entry;
} NacpStruct;
static inline Result nacpGetLanguageEntry(NacpStruct* nacp, NacpLanguageEntry** langentry)
{
if(nacp && langentry)
{
*langentry = &nacp->entry;
return 0;
}
return 0xBAD;
}

View File

@@ -1,120 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ns.h"
#include "types.h"
#include <string.h>
#include <stdlib.h>
#define GAME_ICON_PATH "src/ipc/pc_shim/game.jpg"
static NsShimStore* g_store = NULL;
Result nsInitialize()
{
if(!g_store)
{
g_store = new NsShimStore();
g_store->AddRecord(0x010000000000F001ULL, "Secret Maryo Chronicles", GAME_ICON_PATH);
g_store->AddRecord(0x010000000000F002ULL, "Zelda: Mystery of Solarus", GAME_ICON_PATH);
g_store->AddRecord(0x010000000000F003ULL, "AM2R", GAME_ICON_PATH);
g_store->AddRecord(0x010000000000F004ULL, "Mother 4", GAME_ICON_PATH);
g_store->AddRecord(0x01007EF00011E000ULL, "Wrath of the Wild", GAME_ICON_PATH);
}
return 0;
}
void nsExit()
{
if(g_store)
delete g_store;
}
Result nsListApplicationRecord(NsApplicationRecord* out_records, s32 size, s32 offset, s32* out_count)
{
return g_store->ListRecord(out_records, size, offset, out_count) ? 0 : 0xBAD;
}
Result nsGetApplicationControlData(NsApplicationControlSource flag, u64 titleID, NsApplicationControlData* out_data, size_t size, u64* out_size)
{
return g_store->GetControlData(out_data, size, titleID, out_size) ? 0 : 0xBAD;
}
NsShimStore::NsShimStore()
{
this->store = std::map<u64, std::pair<std::string, std::string>>();
}
void NsShimStore::AddRecord(u64 titleID, std::string name, std::string iconPath)
{
this->store[titleID] = std::make_pair(name, iconPath);
}
bool NsShimStore::ListRecord(NsApplicationRecord* out_records, s32 size, s32 offset, s32* out_count)
{
if(!out_records || !out_count)
{
return false;
}
size_t left = size;
size_t count = 0;
std::map<u64, std::pair<std::string, std::string>>::iterator it = this->store.begin();
std::advance(it, offset);
while(left >= sizeof(NsApplicationRecord) && it != this->store.end())
{
out_records->application_id = it->first;
left -= sizeof(NsApplicationRecord);
out_records++;
count++;
std::advance(it, 1);
}
*out_count = count;
return true;
}
bool NsShimStore::GetControlData(NsApplicationControlData* out_data, size_t size, u64 tid, size_t* out_size)
{
if(!out_data || !out_size || size != sizeof(NsApplicationControlData))
{
return false;
}
std::map<u64, std::pair<std::string, std::string>>::iterator it = this->store.find(tid);
if(it == this->store.end())
{
return false;
}
memset(out_data, 0, size);
strncpy(out_data->nacp.entry.name, it->second.first.c_str(), sizeof(out_data->nacp.entry.name)-1);
FILE* f = fopen(it->second.second.c_str(), "rb");
if(!f)
{
printf("[NsShimStore] Could not open file '%s'\n", it->second.second.c_str());
return false;
}
*out_size = fread(out_data->icon, sizeof(out_data->icon), 1, f);
fclose(f);
return true;
}

View File

@@ -1,60 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <map>
#include <string>
#include "../types.h"
#include "types.h"
#include "nacp.h"
typedef enum
{
NsApplicationControlSource_Storage = 1
} NsApplicationControlSource;
typedef struct
{
u64 application_id;
} NsApplicationRecord;
typedef struct
{
NacpStruct nacp;
NsApplicationIcon icon;
} NsApplicationControlData;
Result nsInitialize();
Result nsListApplicationRecord(NsApplicationRecord* out_records, s32 size, s32 offset, s32* out_count);
Result nsGetApplicationControlData(NsApplicationControlSource flag, u64 titleID, NsApplicationControlData* out_data, size_t size, u64* out_size);
void nsExit();
class NsShimStore
{
public:
NsShimStore();
void AddRecord(u64 titleID, std::string name, std::string iconPath);
bool ListRecord(NsApplicationRecord* out_records, s32 size, s32 offset, s32* out_count);
bool GetControlData(NsApplicationControlData* out_data, size_t size, u64 titleID, size_t* out_size);
protected:
std::map<u64, std::pair<std::string, std::string>> store;
};

View File

@@ -1,32 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <cstdint>
#define R_FAILED(res) ((res) != 0)
#define R_SUCCEEDED(res) ((res) == 0)
typedef std::uint32_t Result;
typedef std::uint32_t u32;
typedef std::int32_t s32;
typedef std::uint64_t u64;
typedef std::uint8_t u8;

View File

@@ -1,26 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <stdint.h>
typedef char NsApplicationName[0x201];
typedef uint8_t NsApplicationIcon[0x20000];

View File

@@ -1,75 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019-2020 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "logo.h"
Logo::Logo(LogoStyle style) {
this->logoLabel = new brls::Label(brls::LabelStyle::LIST_ITEM, "sys-clk-OC", style == LogoStyle::ABOUT);
this->logoLabel->setParent(this);
int logoFont = brls::Application::findFont(LOGO_FONT_NAME);
if (logoFont >= 0)
{
this->logoLabel->setFont(logoFont);
}
if (style == LogoStyle::ABOUT)
{
this->logoLabel->setFontSize(LOGO_ABOUT_FONT_SIZE);
this->logoLabel->setHorizontalAlign(NVG_ALIGN_CENTER);
}
if (style == LogoStyle::HEADER)
{
this->logoLabel->setFontSize(LOGO_HEADER_FONT_SIZE);
this->descLabel = new brls::Label(brls::LabelStyle::LIST_ITEM, "manager");
this->descLabel->setParent(this);
this->descLabel->setFontSize(LOGO_DESC_FONT_SIZE);
}
}
Logo::~Logo() {
delete this->logoLabel;
if (this->descLabel)
delete this->descLabel;
}
void Logo::draw(NVGcontext* vg, int x, int y, unsigned width, unsigned height, brls::Style* style, brls::FrameContext* ctx)
{
this->logoLabel->frame(ctx);
if (this->descLabel)
this->descLabel->frame(ctx);
}
void Logo::layout(NVGcontext* vg, brls::Style* style, brls::FontStash* stash)
{
this->logoLabel->setBoundaries(this->x, this->y + LOGO_OFFSET, this->width, this->height);
this->logoLabel->layout(vg, style, stash);
this->height = this->logoLabel->getHeight();
if (this->descLabel)
{
this->descLabel->layout(vg, style, stash);
this->descLabel->setBoundaries(this->x + LOGO_HEADER_SPACING + this->logoLabel->getWidth(), this->y + style->AppletFrame.titleOffset - 1, this->descLabel->getWidth(), height);
}
}

View File

@@ -1,52 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019-2020 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "utils.h"
enum class LogoStyle
{
HEADER = 0,
ABOUT
};
#define LOGO_FONT_NAME "logo"
#define LOGO_FONT_PATH APP_ASSET("fira/FiraSans-Medium-rnx.ttf")
#define LOGO_HEADER_FONT_SIZE 45
#define LOGO_HEADER_SPACING 12
#define LOGO_ABOUT_FONT_SIZE 55
#define LOGO_DESC_FONT_SIZE 28
#define LOGO_OFFSET 2
class Logo : public brls::View
{
protected:
brls::Label* logoLabel = nullptr;
brls::Label* descLabel = nullptr;
void layout(NVGcontext* vg, brls::Style* style, brls::FontStash* stash);
void draw(NVGcontext* vg, int x, int y, unsigned width, unsigned height, brls::Style* style, brls::FrameContext* ctx) override;
public:
Logo(LogoStyle style);
virtual ~Logo();
};

View File

@@ -1,102 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <borealis.hpp>
#include "main_frame.h"
#include "logo.h"
#include "ipc/client.h"
#include "ipc/ipc.h"
int main(int argc, char* argv[])
{
// Init the app
if (!brls::Application::init(APP_TITLE))
{
brls::Logger::error("Unable to init Borealis application");
return EXIT_FAILURE;
}
// Setup verbose logging on PC
#ifndef __SWITCH__
brls::Logger::setLogLevel(brls::LogLevel::DEBUG);
#endif
if (brls::Application::loadFont(LOGO_FONT_NAME, LOGO_FONT_PATH) < 0)
{
brls::Logger::error("failed to load logo font");
}
uint32_t apiVersion;
// Check that sys-clk is running
if (!sysclkIpcRunning())
{
brls::Logger::error("sys-clk is not running");
brls::Application::crash("sys-clk does not seem to be running, please check that it is correctly installed and enabled.");
}
// Initialize sys-clk IPC client
else if (R_FAILED(sysclkIpcInitialize()) || R_FAILED(sysclkIpcGetAPIVersion(&apiVersion)))
{
brls::Logger::error("Unable to initialize sys-clk IPC client");
brls::Application::crash("Could not connect to sys-clk, please check that it is correctly installed and enabled.");
}
else if (SYSCLK_IPC_API_VERSION != apiVersion) {
brls::Logger::error("sys-clk IPC API version mismatch (expected: %u; actual: %u)", SYSCLK_IPC_API_VERSION, apiVersion);
brls::Application::crash("The manager is not compatible with the currently running sysmodule of sys-clk, please check that you have correctly installed the latest version (reboot?).");
}
else
{
// Set version string
char version[0x100] = {0};
Result rc = sysclkIpcGetVersionString(version, sizeof(version));
if (R_SUCCEEDED(rc))
{
brls::Application::setCommonFooter(std::string(version));
}
else
{
brls::Logger::error("Unable to get sys-clk version string");
brls::Application::setCommonFooter("[unknown]");
}
// Initialize services with a PC shim
nsInitialize();
// Create root view
MainFrame *mainFrame = new MainFrame();
// Add the root view to the stack
brls::Application::pushView(mainFrame);
}
// Run the app
while (brls::Application::mainLoop());
// Exit
nsExit();
sysclkIpcExit();
return EXIT_SUCCESS;
}

View File

@@ -1,56 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019-2020 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "main_frame.h"
#include "status_tab.h"
#include "advanced_settings_tab.h"
#include "app_profiles_tab.h"
// #include "cheat_sheet_tab.h"
#include "about_tab.h"
#include "logo.h"
#include "ipc/client.h"
MainFrame::MainFrame() : TabFrame()
{
// Start refresh task
this->refreshTask = new RefreshTask();
this->refreshTask->start();
// Load UI
this->setIcon(new Logo(LogoStyle::HEADER));
AppProfilesTab *tab = new AppProfilesTab();
this->addTab("Status", new StatusTab(this->refreshTask));
this->addTab("Application Profiles", tab);
this->addTab("Advanced Settings", new AdvancedSettingsTab());
this->addSeparator();
// this->addTab("Cheat Sheet", new CheatSheetTab());
this->addTab("About", new AboutTab());
}
MainFrame::~MainFrame()
{
this->refreshTask->stop();
}

View File

@@ -1,35 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "refresh_task.h"
class MainFrame : public brls::TabFrame
{
private:
RefreshTask *refreshTask;
public:
MainFrame();
~MainFrame();
};

View File

@@ -1,93 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "refresh_task.h"
#include "utils.h"
#define REFRESH_INTERVAL 400
RefreshTask::RefreshTask() : RepeatingTask(REFRESH_INTERVAL)
{
}
void RefreshTask::onStart()
{
Result rc = sysclkIpcGetCurrentContext(&this->oldContext);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to get context");
errorResult("sysclkIpcGetCurrentContext", rc);
}
}
void RefreshTask::run(retro_time_t currentTime)
{
RepeatingTask::run(currentTime);
// Get new context
SysClkContext context;
if (R_SUCCEEDED(sysclkIpcGetCurrentContext(&context)))
{
// CPU Freq
if (context.freqs[SysClkModule_CPU] != this->oldContext.freqs[SysClkModule_CPU])
this->freqUpdateEvent.fire(SysClkModule_CPU, context.freqs[SysClkModule_CPU]);
// GPU Freq
if (context.freqs[SysClkModule_GPU] != this->oldContext.freqs[SysClkModule_GPU])
this->freqUpdateEvent.fire(SysClkModule_GPU, context.freqs[SysClkModule_GPU]);
// MEM Freq
if (context.freqs[SysClkModule_MEM] != this->oldContext.freqs[SysClkModule_MEM])
this->freqUpdateEvent.fire(SysClkModule_MEM, context.freqs[SysClkModule_MEM]);
// Application ID
if (context.applicationId != this->oldContext.applicationId)
this->appIdUpdateEvent.fire(context.applicationId);
// Profile
if (context.profile != this->oldContext.profile)
this->profileUpdateEvent.fire(context.profile);
// Only notify temp changes every other tick
if (this->shouldNotifyTempChange)
{
// PCB Temp
if (context.temps[SysClkThermalSensor_PCB] != this->oldContext.temps[SysClkThermalSensor_PCB])
this->tempUpdateEvent.fire(SysClkThermalSensor_PCB, context.temps[SysClkThermalSensor_PCB]);
//SoC Temp
if (context.temps[SysClkThermalSensor_SOC] != this->oldContext.temps[SysClkThermalSensor_SOC])
this->tempUpdateEvent.fire(SysClkThermalSensor_SOC, context.temps[SysClkThermalSensor_SOC]);
//Skin Temp
if (context.temps[SysClkThermalSensor_Skin] != this->oldContext.temps[SysClkThermalSensor_Skin])
this->tempUpdateEvent.fire(SysClkThermalSensor_Skin, context.temps[SysClkThermalSensor_Skin]);
}
this->shouldNotifyTempChange = !this->shouldNotifyTempChange;
this->oldContext = context;
}
else
{
brls::Logger::error("Unable to refresh context");
}
}

View File

@@ -1,80 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "ipc/client.h"
#include <functional>
typedef brls::Event<SysClkModule, uint32_t> FreqUpdateEvent;
typedef brls::Event<uint64_t> AppIdUpdateEvent;
typedef brls::Event<SysClkProfile> ProfileUpdateEvent;
typedef brls::Event<SysClkThermalSensor, uint32_t> TempUpdateEvent;
class RefreshTask : public brls::RepeatingTask
{
private:
SysClkContext oldContext;
FreqUpdateEvent freqUpdateEvent;
AppIdUpdateEvent appIdUpdateEvent;
ProfileUpdateEvent profileUpdateEvent;
TempUpdateEvent tempUpdateEvent;
bool shouldNotifyTempChange = true;
public:
RefreshTask();
~RefreshTask() {}
void onStart() override;
void run(retro_time_t currentTime) override;
inline FreqUpdateEvent::Subscription registerFreqListener(FreqUpdateEvent::Callback cb) {
return this->freqUpdateEvent.subscribe(cb);
}
inline void unregisterFreqListener(FreqUpdateEvent::Subscription subscription) {
this->freqUpdateEvent.unsubscribe(subscription);
}
inline AppIdUpdateEvent::Subscription registerAppIdListener(AppIdUpdateEvent::Callback cb) {
return this->appIdUpdateEvent.subscribe(cb);
}
inline void unregisterAppIdListener(AppIdUpdateEvent::Subscription subscription) {
this->appIdUpdateEvent.unsubscribe(subscription);
}
inline ProfileUpdateEvent::Subscription registerProfileListener(ProfileUpdateEvent::Callback cb) {
return this->profileUpdateEvent.subscribe(cb);
}
inline void unregisterProfileListener(ProfileUpdateEvent::Subscription subscription) {
this->profileUpdateEvent.unsubscribe(subscription);
}
inline TempUpdateEvent::Subscription registerTempListener(TempUpdateEvent::Callback cb) {
return this->tempUpdateEvent.subscribe(cb);
}
inline void unregisterTempListener(TempUpdateEvent::Subscription subscription) {
this->tempUpdateEvent.unsubscribe(subscription);
}
};

View File

@@ -1,314 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "status_tab.h"
#include "ipc/client.h"
#include "utils.h"
#define DANGEROUS_TEMP_THRESHOLD 84000
#define DANGEROUS_TEMP_COLOR nvgRGB(255, 85, 0)
StatusTab::StatusTab(RefreshTask *refreshTask) :
brls::List(),
refreshTask(refreshTask)
{
// Get context
SysClkContext context;
Result rc = sysclkIpcGetCurrentContext(&context);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to get context");
errorResult("sysclkIpcGetCurrentContext", rc);
brls::Application::crash("Could not get the current sys-clk context, please check that it is correctly installed and enabled.");
return;
}
// Customize list
this->setSpacing(this->getSpacing() / 2);
this->setMarginBottom(20);
// Enabled option
brls::ToggleListItem *serviceEnabledListItem = new brls::ToggleListItem("Enable service", context.enabled, "", "Yes", "No");
serviceEnabledListItem->getClickEvent()->subscribe([this, serviceEnabledListItem](View* view)
{
bool enabled = serviceEnabledListItem->getToggleState();
brls::Logger::info("New service state = %d", enabled);
Result rc = sysclkIpcSetEnabled(enabled);
if (R_FAILED(rc))
{
brls::Logger::error("Unable to set enabled state");
errorResult("sysclkIpcSetEnabled", rc);
// TODO: Put it back to on / off
}
this->refreshTask->fireNow();
});
this->addView(serviceEnabledListItem);
// Frequencies
brls::Header *hardwareHeader = new brls::Header("Hardware");
this->addView(hardwareHeader);
StatusGrid *frequenciesLayout = new StatusGrid();
frequenciesLayout->setSpacing(22);
frequenciesLayout->setHeight(40);
this->cpuFreqCell = new StatusCell("CPU", formatFreq(context.freqs[SysClkModule_CPU]));
this->gpuFreqCell = new StatusCell("GPU", formatFreq(context.freqs[SysClkModule_GPU]));
this->memFreqCell = new StatusCell("MEM", formatFreq(context.freqs[SysClkModule_MEM]));
frequenciesLayout->addView(this->cpuFreqCell);
frequenciesLayout->addView(this->gpuFreqCell);
frequenciesLayout->addView(this->memFreqCell);
this->addView(frequenciesLayout);
// Temperatures
StatusGrid *tempsLayout = new StatusGrid();
tempsLayout->setSpacing(22);
tempsLayout->setHeight(40);
this->skinTempCell = new StatusCell("Skin", formatTemp(context.temps[SysClkThermalSensor_Skin]));
this->socTempCell = new StatusCell("SOC", formatTemp(context.temps[SysClkThermalSensor_SOC]));
this->pcbTempCell = new StatusCell("PCB", formatTemp(context.temps[SysClkThermalSensor_PCB]));
if (context.temps[SysClkThermalSensor_SOC] > DANGEROUS_TEMP_THRESHOLD)
this->socTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
if (context.temps[SysClkThermalSensor_PCB] > DANGEROUS_TEMP_THRESHOLD)
this->pcbTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
if (context.temps[SysClkThermalSensor_Skin] > DANGEROUS_TEMP_THRESHOLD)
this->skinTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
tempsLayout->addView(this->socTempCell);
tempsLayout->addView(this->pcbTempCell);
tempsLayout->addView(this->skinTempCell);
this->addView(tempsLayout);
// Info
brls::Header *systemHeader = new brls::Header("System");
this->addView(systemHeader);
InfoGrid *infoLayout = new InfoGrid();
infoLayout->setSpacing(22);
infoLayout->setHeight(40);
this->profileCell = new StatusCell("Profile", formatProfile(context.profile));
this->tidCell = new StatusCell("Application ID", formatTid(context.applicationId));
infoLayout->addView(this->profileCell);
infoLayout->addView(this->tidCell);
this->addView(infoLayout);
// Warning label
warningLabel = new brls::Label(brls::LabelStyle::SMALL, "");
warningLabel->setVerticalAlign(NVG_ALIGN_BOTTOM);
warningLabel->setHorizontalAlign(NVG_ALIGN_RIGHT);
this->addView(warningLabel, true);
updateWarningForProfile(context.profile, false);
// Setup refresh task
this->freqListenerSub = refreshTask->registerFreqListener([this](SysClkModule module, uint32_t freq) {
switch(module)
{
case SysClkModule_CPU:
this->cpuFreqCell->setValue(formatFreq(freq));
break;
case SysClkModule_GPU:
this->gpuFreqCell->setValue(formatFreq(freq));
break;
case SysClkModule_MEM:
this->memFreqCell->setValue(formatFreq(freq));
break;
default:
break;
}
});
this->appIdListenerSub = refreshTask->registerAppIdListener([this](uint64_t tid) {
this->tidCell->setValue(formatTid(tid));
});
this->profileListenerSub = refreshTask->registerProfileListener([this](SysClkProfile profile) {
this->profileCell->setValue(formatProfile(profile));
updateWarningForProfile(profile, true);
});
this->tempListenerSub = refreshTask->registerTempListener([this](SysClkThermalSensor sensor, uint32_t temp) {
switch (sensor)
{
case SysClkThermalSensor_PCB:
this->pcbTempCell->setValue(formatTemp(temp));
if (temp > DANGEROUS_TEMP_THRESHOLD)
this->pcbTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
else
this->pcbTempCell->resetValueColor();
break;
case SysClkThermalSensor_SOC:
this->socTempCell->setValue(formatTemp(temp));
if (temp > DANGEROUS_TEMP_THRESHOLD)
this->socTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
else
this->socTempCell->resetValueColor();
break;
case SysClkThermalSensor_Skin:
this->skinTempCell->setValue(formatTemp(temp));
if (temp > DANGEROUS_TEMP_THRESHOLD)
this->skinTempCell->setValueColor(DANGEROUS_TEMP_COLOR);
else
this->skinTempCell->resetValueColor();
break;
default:
break;
}
});
}
void StatusTab::updateWarningForProfile(SysClkProfile profile, bool animated)
{
// switch (profile)
// {
// case SysClkProfile_Handheld:
// if (this->warningLabel->isHidden())
// this->warningLabel->show([](){});
// this->warningLabel->setText("\uE140 Handheld Mode: Max GPU freq: " + formatFreq(SYSCLK_GPU_HANDHELD_MAX_HZ));
// break;
// case SysClkProfile_HandheldChargingUSB:
// if (this->warningLabel->isHidden())
// this->warningLabel->show([](){});
// this->warningLabel->setText("\uE140 USB Charging Mode: Max GPU freq: " + formatFreq(SYSCLK_GPU_CHARGING_USB_MAX_HZ));
// break;
// default:
// if (!this->warningLabel->isHidden())
// this->warningLabel->hide([](){}, animated);
// break;
// }
}
StatusTab::~StatusTab()
{
refreshTask->unregisterFreqListener(this->freqListenerSub);
refreshTask->unregisterAppIdListener(this->appIdListenerSub);
refreshTask->unregisterProfileListener(this->profileListenerSub);
refreshTask->unregisterTempListener(this->tempListenerSub);
}
StatusGrid::StatusGrid()
: BoxLayout(brls::BoxLayoutOrientation::HORIZONTAL)
{
}
void StatusGrid::layout(NVGcontext* vg, brls::Style *style, brls::FontStash *stash)
{
// Distribute space equally between children
if (!this->children.empty())
{
size_t size = this->children.size();
unsigned width = (this->getWidth()- this->marginLeft - this->marginRight - this->getSpacing() * (size - 1)) / size;
for (brls::BoxLayoutChild *child : this->children)
{
if (!child->fill)
child->view->setWidth(width);
}
}
// Layout normally
BoxLayout::layout(vg, style, stash);
}
InfoGrid::InfoGrid() : BoxLayout(brls::BoxLayoutOrientation::HORIZONTAL)
{
}
void InfoGrid::layout(NVGcontext* vg, brls::Style *style, brls::FontStash *stash)
{
// Give first child one third of the view, give second child the rest
if (this->children.size() >= 2)
{
size_t size = 3;
unsigned firstWidth = (this->getWidth()- this->marginLeft - this->marginRight - this->getSpacing() * (size - 1)) / size;
unsigned secondWidth = firstWidth * 2 + this->getSpacing();
this->children[0]->view->setWidth(firstWidth);
this->children[1]->view->setWidth(secondWidth);
}
// Layout normally
BoxLayout::layout(vg, style, stash);
}
StatusCell::StatusCell(std::string label, std::string value) : label(label), value(value)
{
this->resetValueColor();
}
void StatusCell::setValue(std::string value)
{
this->value = value;
}
void StatusCell::draw(NVGcontext *vg, int x, int y, unsigned width, unsigned height, brls::Style *style, brls::FrameContext *ctx)
{
unsigned padding = 5;
// Label
nvgBeginPath(vg);
nvgFillColor(vg, a(ctx->theme->tableBodyTextColor));
nvgFontSize(vg, 16);
nvgTextAlign(vg, NVG_ALIGN_LEFT | NVG_ALIGN_BASELINE);
nvgText(vg, x + padding, y + height / 2, this->label.c_str(), nullptr);
// Value
nvgBeginPath(vg);
nvgFillColor(vg, a(this->valueColor));
nvgFontSize(vg, 20);
nvgTextAlign(vg, NVG_ALIGN_RIGHT | NVG_ALIGN_BASELINE);
nvgText(vg, x + width - padding, y + height / 2, this->value.c_str(), nullptr);
}
void StatusCell::setValueColor(NVGcolor color)
{
this->valueColor = color;
}
void StatusCell::resetValueColor()
{
this->valueColor = brls::Application::getThemeValues()->textColor;
}

View File

@@ -1,89 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <borealis.hpp>
#include "refresh_task.h"
class StatusCell : public brls::View
{
private:
std::string label;
std::string value;
NVGcolor valueColor;
public:
StatusCell(std::string label, std::string value);
void draw(NVGcontext *vg, int x, int y, unsigned width, unsigned height, brls::Style *style, brls::FrameContext *ctx) override;
void setValue(std::string value);
void setValueColor(NVGcolor color);
void resetValueColor();
};
class InfoGrid : public brls::BoxLayout
{
public:
InfoGrid();
void layout(NVGcontext* vg, brls::Style *style, brls::FontStash *stash) override;
};
class StatusGrid : public brls::BoxLayout
{
public:
StatusGrid();
void layout(NVGcontext* vg, brls::Style *style, brls::FontStash *stash) override;
};
class StatusTab : public brls::List
{
private:
RefreshTask *refreshTask;
FreqUpdateEvent::Subscription freqListenerSub;
AppIdUpdateEvent::Subscription appIdListenerSub;
ProfileUpdateEvent::Subscription profileListenerSub;
TempUpdateEvent::Subscription tempListenerSub;
StatusCell *cpuFreqCell;
StatusCell *gpuFreqCell;
StatusCell *memFreqCell;
StatusCell *socTempCell;
StatusCell *pcbTempCell;
StatusCell *skinTempCell;
StatusCell *profileCell;
StatusCell *tidCell;
brls::Label *warningLabel;
void updateWarningForProfile(SysClkProfile profile, bool animated);
public:
StatusTab(RefreshTask *refreshTask);
~StatusTab();
};

View File

@@ -1,124 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "utils.h"
#include <borealis.hpp>
std::string formatFreq(uint32_t freq)
{
char str[16];
snprintf(str, sizeof(str), "%.1f MHz", (float)freq / 1000000.0f);
return std::string(str);
}
std::string formatTid(uint64_t tid)
{
char str[17];
snprintf(str, sizeof(str), "%016lX", tid);
return std::string(str);
}
std::string formatProfile(SysClkProfile profile)
{
return std::string(sysclkFormatProfile(profile, true));
}
std::string formatTemp(uint32_t temp)
{
char str[16];
snprintf(str, sizeof(str), "%.1f °C", (float)temp / 1000.0f);
return std::string(str);
}
void errorResult(std::string tag, Result rc)
{
#ifdef __SWITCH__
brls::Logger::error("[0x%x] %s failed - %04d-%04d", rc, tag.c_str(), R_MODULE(rc), R_DESCRIPTION(rc));
#else
brls::Logger::error("[0x%x] %s failed - xxxx-xxxx", rc, tag.c_str());
#endif
}
// TODO: Merge ticker for single line labels in Borealis and remove usage of this
std::string formatListItemTitle(const std::string str, size_t maxScore) {
size_t score = 0;
for (size_t i = 0; i < str.length(); i++)
{
score += std::isupper(str[i]) ? 4 : 3;
if(score > maxScore)
{
return str.substr(0, i-1) + "\u2026";
}
}
return str;
}
brls::SelectListItem* createFreqListItem(SysClkModule module, uint32_t selectedFreqInMhz, std::string defaultString)
{
std::string name;
uint32_t* table;
switch (module)
{
case SysClkModule_CPU:
name = "CPU Frequency";
table = g_freq_table_cpu_hz;
break;
case SysClkModule_GPU:
name = "GPU Frequency";
table = g_freq_table_gpu_hz;
break;
case SysClkModule_MEM:
name = "MEM Frequency";
table = g_freq_table_mem_hz;
break;
default:
return nullptr;
}
size_t selected = 0;
size_t i = 0;
std::vector<std::string> clocks;
clocks.push_back(defaultString);
while (table[i] != 0)
{
uint32_t freq = table[i];
if (freq / 1000000 == selectedFreqInMhz)
selected = i + 1;
char clock[16];
if (freq == 1862400000)
snprintf(clock, sizeof(clock), "Maximum");
else
snprintf(clock, sizeof(clock), "%d MHz", freq / 1000000);
clocks.push_back(std::string(clock));
i++;
}
return new brls::SelectListItem(name, clocks, selected);
}

View File

@@ -1,40 +0,0 @@
/*
sys-clk manager, a sys-clk frontend homebrew
Copyright (C) 2019 natinusala
Copyright (C) 2019 p-sam
Copyright (C) 2019 m4xw
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include <string>
#include <sysclk/clocks.h>
#include "ipc/ipc.h"
#include <borealis.hpp>
#define APP_ASSET(p) APP_RESOURCES p
std::string formatListItemTitle(const std::string str, size_t maxScore = 140);
brls::SelectListItem* createFreqListItem(SysClkModule module, uint32_t selectedFreqInMhz, std::string defaultString = "Do not override");
std::string formatFreq(uint32_t freq);
std::string formatTid(uint64_t tid);
std::string formatProfile(SysClkProfile profile);
std::string formatTemp(uint32_t temp);
void errorResult(std::string tag, Result rc);