Skip to content

Commit

Permalink
Integrate fix for ITotalJustice#66.
Browse files Browse the repository at this point in the history
Signed-off-by: shadow2560 <[email protected]>
  • Loading branch information
shadow2560 committed Dec 31, 2024
1 parent 008b8ee commit ea47d91
Showing 1 changed file with 142 additions and 43 deletions.
185 changes: 142 additions & 43 deletions sphaira/source/app.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "ui/menus/main_menu.hpp"
#include "ui/error_box.hpp"
#include "ui/option_box.hpp"

#include "app.hpp"
#include "log.hpp"
Expand Down Expand Up @@ -389,6 +390,10 @@ auto App::GetThemeIndex() -> u64 {
return g_app->m_theme_index;
}

auto App::GetDefaultImage(int* w, int* h) -> int {
return g_app->m_default_image;
}

auto App::GetExePath() -> fs::FsPath {
return g_app->m_app_path;
}
Expand Down Expand Up @@ -464,7 +469,104 @@ void App::SetLogEnable(bool enable) {
}

void App::SetReplaceHbmenuEnable(bool enable) {
g_app->m_replace_hbmenu.Set(enable);
if (App::GetReplaceHbmenuEnable() != enable) {
g_app->m_replace_hbmenu.Set(enable);
if (!enable) {
// check we have already replaced hbmenu with sphaira
NacpStruct hbmenu_nacp;
if (R_FAILED(nro_get_nacp("/hbmenu.nro", hbmenu_nacp))) {
return;
}

if (std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
return;
}

// ask user if they want to restore hbmenu
App::Push(std::make_shared<ui::OptionBox>(
"Restore hbmenu?"_i18n,
"Back"_i18n, "Restore"_i18n, 1, [hbmenu_nacp](auto op_index){
if (!op_index || *op_index == 0) {
return;
}

NacpStruct actual_hbmenu_nacp;
if (R_FAILED(nro_get_nacp("/switch/hbmenu.nro", actual_hbmenu_nacp))) {
App::Push(std::make_shared<ui::OptionBox>(
"Failed to find /switch/hbmenu.nro\n\
Use the Appstore to re-install hbmenu"_i18n,
"OK"_i18n
));
return;
}

// NOTE: do NOT use rename anywhere here as it's possible
// to have a race condition with another app that opens hbmenu as a file
// in between the delete + rename.
// this would require a sys-module to open hbmenu.nro, such as an ftp server.
// a copy means that it opens the file handle, if successfull, then
// the full read/write will succeed.
fs::FsNativeSd fs;
NacpStruct sphaira_nacp;
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
Result rc;

// first, try and backup sphaira, its not super important if this fails.
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
sphaira_path = "/switch/sphaira.nro";
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
}

if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
if (std::strcmp(sphaira_nacp.display_version, hbmenu_nacp.display_version) < 0) {
if (R_FAILED(rc = fs.copy_entire_file(sphaira_path, "/hbmenu.nro", true))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else {
log_write("success with updating hbmenu!\n");
}
}
} else {
// sphaira doesn't yet exist, create a new file.
sphaira_path = "/switch/sphaira/sphaira.nro";
fs.CreateDirectoryRecursively("/switch/sphaira/");
fs.copy_entire_file(sphaira_path, "/hbmenu.nro", true);
}

// this should never fail, if it does, well then the sd card is fucked.
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", "/switch/hbmenu.nro", true))) {
// try and restore sphaira in a last ditch effort.
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", sphaira_path, true))) {
App::Push(std::make_shared<ui::ErrorBox>(rc,
"Failed to restore hbmenu, please re-download hbmenu"_i18n
));
} else {
App::Push(std::make_shared<ui::OptionBox>(
"Failed to restore hbmenu, using sphaira instead"_i18n,
"OK"_i18n
));
}
return;
}

// don't need this any more.
fs.DeleteFile("/switch/hbmenu.nro", true);

// if we were hbmenu, exit now (as romfs is gone).
if (IsHbmenu()) {
App::Push(std::make_shared<ui::OptionBox>(
"Restored hbmenu, closing sphaira"_i18n,
"OK"_i18n, [](auto) {
App::Exit();
}
));
} else {
App::Notify("Restored hbmenu"_i18n);
}
}
));
}
}
}

void App::SetInstallEnable(bool enable) {
Expand Down Expand Up @@ -593,24 +695,7 @@ void App::Poll() {
m_controller.m_kdown = padGetButtonsDown(&m_pad);
m_controller.m_kheld = padGetButtons(&m_pad);
m_controller.m_kup = padGetButtonsUp(&m_pad);

// dpad
m_controller.UpdateButtonHeld(HidNpadButton_Left);
m_controller.UpdateButtonHeld(HidNpadButton_Right);
m_controller.UpdateButtonHeld(HidNpadButton_Down);
m_controller.UpdateButtonHeld(HidNpadButton_Up);

// ls
m_controller.UpdateButtonHeld(HidNpadButton_StickLLeft);
m_controller.UpdateButtonHeld(HidNpadButton_StickLRight);
m_controller.UpdateButtonHeld(HidNpadButton_StickLDown);
m_controller.UpdateButtonHeld(HidNpadButton_StickLUp);

// rs
m_controller.UpdateButtonHeld(HidNpadButton_StickRLeft);
m_controller.UpdateButtonHeld(HidNpadButton_StickRRight);
m_controller.UpdateButtonHeld(HidNpadButton_StickRDown);
m_controller.UpdateButtonHeld(HidNpadButton_StickRUp);
m_controller.UpdateButtonHeld(static_cast<u64>(Button::ANY_DIRECTION));

HidTouchScreenState touch_state{};
hidGetTouchScreenStates(&touch_state, 1);
Expand Down Expand Up @@ -974,7 +1059,6 @@ App::App(const char* argv0) {
}

curl::Init();
curl::cache::init();

// Create the deko3d device
this->device = dk::DeviceMaker{}
Expand Down Expand Up @@ -1108,6 +1192,15 @@ App::App(const char* argv0) {
log_write("sd_total_space: %zd\n", sd_total_space);
}

// load default image
if (R_SUCCEEDED(romfsInit())) {
ON_SCOPE_EXIT(romfsExit());
const auto image = ImageLoadFromFile("romfs:/default.png");
if (!image.data.empty()) {
m_default_image = nvgCreateImageRGBA(vg, image.w, image.h, 0, image.data.data());
}
}

App::Push(std::make_shared<ui::menu::main::MainMenu>());
log_write("finished app constructor\n");
}
Expand All @@ -1130,11 +1223,11 @@ App::~App() {

i18n::exit();
curl::Exit();
curl::cache::exit();

// this has to be called before any cleanup to ensure the lifetime of
// nvg is still active as some widgets may need to free images.
m_widgets.clear();
nvgDeleteImage(vg, m_default_image);

appletUnhook(&m_appletHookCookie);

Expand All @@ -1161,47 +1254,53 @@ App::~App() {

// backup hbmenu if it is not sphaira
if (App::GetReplaceHbmenuEnable() && !IsHbmenu()) {
NacpStruct nacp;
NacpStruct hbmenu_nacp;
fs::FsNativeSd fs;
if (R_SUCCEEDED(nro_get_nacp("/hbmenu.nro", nacp)) && std::strcmp(nacp.lang[0].name, "sphaira")) {
log_write("backing up \"/hbmenu.nro\"\n");
if (R_FAILED(fs.copy_entire_file("/switch/hbmenu.nro", "/hbmenu.nro", true))) {
log_write("failed to backup \"/hbmenu.nro\"\n");
Result rc;

if (R_SUCCEEDED(rc = nro_get_nacp("/hbmenu.nro", hbmenu_nacp)) && std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
log_write("backing up hbmenu.nro\n");
if (R_FAILED(rc = fs.copy_entire_file("/switch/hbmenu.nro", "/hbmenu.nro", true))) {
log_write("failed to backup hbmenu.nro\n");
}
} else {
log_write("not backing up\n");
}

Result rc;
if (R_FAILED(rc = fs.copy_entire_file("/hbmenu.nro", GetExePath(), true))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", GetExePath(), rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else {
log_write("success with replacing \"/hbmenu.nro\"!\n");
log_write("success with copying over root file!\n");
}
} else if (IsHbmenu()) {
// check we have a version that's newer than current.
NacpStruct hbmenu_nacp;
fs::FsNativeSd fs;
NacpStruct sphaira_nacp;
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";
Result rc;

rc = nro_get_nacp(sphaira_path, sphaira_nacp);
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
sphaira_path = "/switch/sphaira.nro";
// ensure that are still sphaira
if (R_SUCCEEDED(rc = nro_get_nacp("/hbmenu.nro", hbmenu_nacp)) && !std::strcmp(hbmenu_nacp.lang[0].name, "sphaira")) {
NacpStruct sphaira_nacp;
fs::FsPath sphaira_path = "/switch/sphaira/sphaira.nro";

rc = nro_get_nacp(sphaira_path, sphaira_nacp);
}
if (R_FAILED(rc) || std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
sphaira_path = "/switch/sphaira.nro";
rc = nro_get_nacp(sphaira_path, sphaira_nacp);
}

// found sphaira, now lets get compare version
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
NacpStruct actual_nacp;
rc = nro_get_nacp(GetExePath(), actual_nacp);
if ((R_SUCCEEDED(rc) && std::strcmp(actual_nacp.display_version, sphaira_nacp.display_version) < 0 && std::strcmp(APP_VERSION, actual_nacp.display_version) <= 0) || R_FAILED(rc)) {
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path, true))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else {
log_write("success with updating hbmenu!\n");
// found sphaira, now lets get compare version
if (R_SUCCEEDED(rc) && !std::strcmp(sphaira_nacp.lang[0].name, "sphaira")) {
if (std::strcmp(hbmenu_nacp.display_version, sphaira_nacp.display_version) < 0) {
if (R_FAILED(rc = fs.copy_entire_file(GetExePath(), sphaira_path, true))) {
log_write("failed to copy entire file: %s 0x%X module: %u desc: %u\n", sphaira_path, rc, R_MODULE(rc), R_DESCRIPTION(rc));
} else {
log_write("success with updating hbmenu!\n");
}
}
}
} else {
log_write("no longer hbmenu!\n");
}
}

Expand Down

0 comments on commit ea47d91

Please sign in to comment.