Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build-jobs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v5
with:
fetch-tags: true
path: sys-patch
Expand All @@ -35,7 +35,7 @@ jobs:
echo "SHA256=${SHA256}" >> $GITHUB_ENV

- name: Upload artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
include-hidden-files: true
overwrite: true
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ MAKEFILES := sysmod overlay
TARGETS := $(foreach dir,$(MAKEFILES),$(CURDIR)/$(dir))

# the below was taken from atmosphere + switch-examples makefile
export VERSION := 1.6.0
export VERSION := 1.6.2.0

ifneq ($(strip $(shell git symbolic-ref --short HEAD 2>/dev/null)),)
export GIT_BRANCH := $(shell git symbolic-ref --short HEAD)
Expand Down
121 changes: 105 additions & 16 deletions overlay/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#define TESLA_INIT_IMPL // If you have more than one file using the tesla header, only define this in the main one
#define STBTT_STATIC
#include <tesla.hpp> // The Tesla Header
#include <string>
#include <string_view>
#include "minIni/minIni.h"

Expand All @@ -9,6 +10,87 @@ namespace {
constexpr auto CONFIG_PATH = "/config/sys-patch/config.ini";
constexpr auto LOG_PATH = "/config/sys-patch/log.ini";

auto split_log_value(std::string_view value) -> std::pair<std::string, std::string> {
if (value.empty()) {
return {{}, {}};
}

const auto offset_start = value.rfind(" (0x");
if (offset_start == std::string_view::npos || value.back() != ')') {
return {std::string{value}, {}};
}

return {
std::string{value.substr(0, offset_start)},
std::string{value.substr(offset_start + 1, value.size() - offset_start - 2)}
};
}

class ColouredListItem : public tsl::elm::ListItem {
public:
ColouredListItem(const std::string& text, const std::string& value, tsl::Color value_colour)
: tsl::elm::ListItem(text, value), m_value_colour(value_colour) {
}

void draw(tsl::gfx::Renderer *renderer) override {
if (this->m_touched && Element::getInputMode() == tsl::InputMode::Touch) {
renderer->drawRect(ELEMENT_BOUNDS(this), a(tsl::style::color::ColorClickAnimation));
}

if (this->m_maxWidth == 0) {
if (!this->m_value.empty()) {
auto [valueWidth, valueHeight] = renderer->drawString(this->m_value.c_str(), false, 0, 0, 20, tsl::style::color::ColorTransparent);
this->m_maxWidth = this->getWidth() - valueWidth - 70;
} else {
this->m_maxWidth = this->getWidth() - 40;
}

auto [width, height] = renderer->drawString(this->m_text.c_str(), false, 0, 0, 23, tsl::style::color::ColorTransparent);
this->m_trunctuated = width > this->m_maxWidth;

if (this->m_trunctuated) {
this->m_scrollText = this->m_text + " ";
auto [scrollWidth, scrollHeight] = renderer->drawString(this->m_scrollText.c_str(), false, 0, 0, 23, tsl::style::color::ColorTransparent);
this->m_scrollText += this->m_text;
this->m_textWidth = scrollWidth;
this->m_ellipsisText = renderer->limitStringLength(this->m_text, false, 22, this->m_maxWidth);
} else {
this->m_textWidth = width;
}
}

renderer->drawRect(this->getX(), this->getY(), this->getWidth(), 1, a(tsl::style::color::ColorFrame));
renderer->drawRect(this->getX(), this->getTopBound(), this->getWidth(), 1, a(tsl::style::color::ColorFrame));

if (this->m_trunctuated) {
if (this->m_focused) {
renderer->enableScissoring(this->getX(), this->getY(), this->m_maxWidth + 40, this->getHeight());
renderer->drawString(this->m_scrollText.c_str(), false, this->getX() + 20 - this->m_scrollOffset, this->getY() + 45, 23, tsl::style::color::ColorText);
renderer->disableScissoring();
if (this->m_scrollAnimationCounter == 90) {
if (this->m_scrollOffset == this->m_textWidth) {
this->m_scrollOffset = 0;
this->m_scrollAnimationCounter = 0;
} else {
this->m_scrollOffset++;
}
} else {
this->m_scrollAnimationCounter++;
}
} else {
renderer->drawString(this->m_ellipsisText.c_str(), false, this->getX() + 20, this->getY() + 45, 23, a(tsl::style::color::ColorText));
}
} else {
renderer->drawString(this->m_text.c_str(), false, this->getX() + 20, this->getY() + 45, 23, a(tsl::style::color::ColorText));
}

renderer->drawString(this->m_value.c_str(), false, this->getX() + this->m_maxWidth + 45, this->getY() + 45, 20, a(m_value_colour));
}

private:
tsl::Color m_value_colour;
};

auto does_file_exist(const char* path) -> bool {
Result rc{};
FsFileSystem fs{};
Expand Down Expand Up @@ -120,6 +202,9 @@ class GuiToggle final : public tsl::Gui {
list->addItem(config_es4.create_list_item("es_19.0.0-21.2.0"));
list->addItem(config_es5.create_list_item("es_22.0.0+"));

list->addItem(new tsl::elm::CategoryHeader("AM - 0100000000000023"));
list->addItem(config_am1.create_list_item("am_homebrew_fix_22.0.0+"));

list->addItem(new tsl::elm::CategoryHeader("OLSC - 010000000000003E"));
list->addItem(config_olsc1.create_list_item("olsc_6.0.0-14.1.2"));
list->addItem(config_olsc2.create_list_item("olsc_15.0.0-18.1.0"));
Expand All @@ -133,10 +218,13 @@ class GuiToggle final : public tsl::Gui {
list->addItem(config_nim1.create_list_item("blankcal0crashfix_17.0.0+"));
list->addItem(config_nim_fw1.create_list_item("blockfirmwareupdates_1.0.0-5.1.0"));
list->addItem(config_nim_fw2.create_list_item("blockfirmwareupdates_6.0.0-6.2.0"));
list->addItem(config_nim_fw3.create_list_item("blockfirmwareupdates_7.0.0-10.2.0"));
list->addItem(config_nim_fw3.create_list_item("blockfirmwareupdates_7.0.0-10.2.0"));
list->addItem(config_nim_fw4.create_list_item("blockfirmwareupdates_11.0.0-11.0.1"));
list->addItem(config_nim_fw5.create_list_item("blockfirmwareupdates_12.0.0+"));

list->addItem(new tsl::elm::CategoryHeader("NS - 010000000000001F"));
list->addItem(config_ns1.create_list_item("force_gamecard_region_to_global"));

frame->setContent(list);
return frame;
}
Expand All @@ -155,6 +243,7 @@ class GuiToggle final : public tsl::Gui {
ConfigEntry config_es3{"es", "es_12.0.0-18.1.0", true};
ConfigEntry config_es4{"es", "es_19.0.0-21.2.0", true};
ConfigEntry config_es5{"es", "es_22.0.0+", true};
ConfigEntry config_am1{"am", "am_homebrew_fix_22.0.0+ ", true};
ConfigEntry config_olsc1{"olsc", "olsc_6.0.0-14.1.2", true};
ConfigEntry config_olsc2{"olsc", "olsc_15.0.0-18.1.0", true};
ConfigEntry config_olsc3{"olsc", "olsc_19.0.0+", true};
Expand All @@ -166,6 +255,7 @@ class GuiToggle final : public tsl::Gui {
ConfigEntry config_nim_fw3{"nim", "blockfirmwareupdates_7.0.0-10.2.0", true};
ConfigEntry config_nim_fw4{"nim", "blockfirmwareupdates_11.0.0-11.0.1", true};
ConfigEntry config_nim_fw5{"nim", "blockfirmwareupdates_12.0.0+", true};
ConfigEntry config_ns1{"ns", "force_gamecard_region_to_global", true};
};

class GuiLog final : public tsl::Gui {
Expand All @@ -185,8 +275,9 @@ class GuiLog final : public tsl::Gui {
ini_browse([](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData){
auto user = (CallbackUser*)UserData;
std::string_view value{Value};
const auto [status, detail] = split_log_value(value);

if (value == "Skipped") {
if (status == "Skipped") {
return 1;
}

Expand All @@ -201,22 +292,20 @@ class GuiLog final : public tsl::Gui {
constexpr tsl::Color colour_unpatched{F(250), F(90), F(58), F(255)};
#undef F

if (value.starts_with("Patched")) {
auto *item = new tsl::elm::ListItem(Key);
item->setValue("Patched", true);
user->list->addItem(item);
} else if (value.starts_with("Unpatched") || value.starts_with("Disabled")) {
auto *item = new tsl::elm::ListItem(Key);
item->setValue(Value, true);
user->list->addItem(item);
if (status.starts_with("Patched")) {
const auto is_sys_patch = status.ends_with("(sys-patch)");
const auto display_value = detail.empty() ? std::string{"Patched"} : "Patched @ " + detail;
user->list->addItem(new ColouredListItem(
Key,
display_value,
is_sys_patch ? colour_syspatch : colour_file
));
} else if (status.starts_with("Unpatched") || status.starts_with("Disabled")) {
user->list->addItem(new ColouredListItem(Key, Value, colour_unpatched));
} else if (user->last_section == "stats") {
auto *item = new tsl::elm::ListItem(Key);
item->setValue(Value, true);
user->list->addItem(item);
user->list->addItem(new ColouredListItem(Key, Value, tsl::style::color::ColorDescription));
} else {
auto *item = new tsl::elm::ListItem(Key);
item->setValue(Value, true);
user->list->addItem(item);
user->list->addItem(new ColouredListItem(Key, Value, tsl::style::color::ColorText));
}

return 1;
Expand Down
Loading