From f7c5ccfa878ff00eeecf8175408ab054ab68dc0a Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Sun, 25 May 2025 20:57:03 +0100 Subject: [PATCH] huge optimisations (see below). Build with c++26 and c23. - build with c++26 and c23, fixes warnings due to this change. - use #embed over romfs where applicable. - load all configs upfront in the app menu, massively improves boot time - enable boost mode during load/scan time in all (slow loading) menus, huge load time improvement. - enable boost mode when exiting the app, to speed up closing all the menus and saving the config. - reduce the size of the nro nacp when loading to just the title + author + display version. - add option to enable boost mode for all progress bar menus, huge perf improvement again. - remove unused launch_count var from the playlog file. - display full path when dumping. - optimise appstore unzip code by iterating through the zip rather than finding a specific file, reduces retroarch extract time from 52s to 26s. overall, this commit has reduced boot time from 0.4s to 0.3s and massively increased load times of other menus. (it also reduced the binary size by 4kb, so yay) --- assets/{romfs => embed/icons}/GET.png | Bin assets/{romfs => embed/icons}/INSTALLED.png | Bin assets/{romfs => embed/icons}/LOCAL.png | Bin assets/{romfs => embed/icons}/UPDATE.png | Bin assets/{romfs => embed/icons}/default.png | Bin hbl/CMakeLists.txt | 6 +- sphaira/CMakeLists.txt | 19 +- sphaira/include/app.hpp | 5 +- sphaira/include/nro.hpp | 12 +- sphaira/include/option.hpp | 5 + sphaira/include/owo.hpp | 4 - sphaira/include/ui/menus/homebrew.hpp | 2 +- sphaira/include/yati/yati.hpp | 4 - sphaira/source/app.cpp | 126 +++++++----- sphaira/source/dumper.cpp | 12 +- sphaira/source/nro.cpp | 16 +- sphaira/source/option.cpp | 48 +++++ sphaira/source/owo.cpp | 18 +- sphaira/source/ui/menus/appstore.cpp | 202 ++++++++++++++------ sphaira/source/ui/menus/filebrowser.cpp | 16 +- sphaira/source/ui/menus/game_menu.cpp | 3 + sphaira/source/ui/menus/gc_menu.cpp | 3 + sphaira/source/ui/menus/homebrew.cpp | 13 +- sphaira/source/ui/menus/themezer.cpp | 3 + sphaira/source/ui/progress_box.cpp | 6 + sphaira/source/yati/yati.cpp | 9 - 26 files changed, 351 insertions(+), 181 deletions(-) rename assets/{romfs => embed/icons}/GET.png (100%) rename assets/{romfs => embed/icons}/INSTALLED.png (100%) rename assets/{romfs => embed/icons}/LOCAL.png (100%) rename assets/{romfs => embed/icons}/UPDATE.png (100%) rename assets/{romfs => embed/icons}/default.png (100%) diff --git a/assets/romfs/GET.png b/assets/embed/icons/GET.png similarity index 100% rename from assets/romfs/GET.png rename to assets/embed/icons/GET.png diff --git a/assets/romfs/INSTALLED.png b/assets/embed/icons/INSTALLED.png similarity index 100% rename from assets/romfs/INSTALLED.png rename to assets/embed/icons/INSTALLED.png diff --git a/assets/romfs/LOCAL.png b/assets/embed/icons/LOCAL.png similarity index 100% rename from assets/romfs/LOCAL.png rename to assets/embed/icons/LOCAL.png diff --git a/assets/romfs/UPDATE.png b/assets/embed/icons/UPDATE.png similarity index 100% rename from assets/romfs/UPDATE.png rename to assets/embed/icons/UPDATE.png diff --git a/assets/romfs/default.png b/assets/embed/icons/default.png similarity index 100% rename from assets/romfs/default.png rename to assets/embed/icons/default.png diff --git a/hbl/CMakeLists.txt b/hbl/CMakeLists.txt index 1147739..b3a3e06 100644 --- a/hbl/CMakeLists.txt +++ b/hbl/CMakeLists.txt @@ -78,11 +78,13 @@ function(nx_create_npdm target config) dkp_set_target_file(${outtarget} "${NX_NPDM_OUTPUT}") endfunction() +file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/exefs) + nx_create_nso(hbl - OUTPUT main + OUTPUT exefs/main ) nx_create_npdm(hbl - OUTPUT main.npdm + OUTPUT exefs/main.npdm CONFIG ${CMAKE_CURRENT_SOURCE_DIR}/hbl.json ) diff --git a/sphaira/CMakeLists.txt b/sphaira/CMakeLists.txt index 08e7c97..c629e27 100644 --- a/sphaira/CMakeLists.txt +++ b/sphaira/CMakeLists.txt @@ -147,8 +147,6 @@ target_compile_options(sphaira PRIVATE -Wimplicit-fallthrough=5 -Wsuggest-final-types -Wuninitialized - -fimplicit-constexpr - -Wmissing-requires ) include(FetchContent) @@ -314,9 +312,9 @@ if (NOT USE_NEW_ZSTD) endif() set_target_properties(sphaira PROPERTIES - C_STANDARD 11 + C_STANDARD 23 C_EXTENSIONS ON - CXX_STANDARD 23 + CXX_STANDARD 26 CXX_EXTENSIONS ON ) @@ -357,12 +355,13 @@ file(COPY ${CMAKE_SOURCE_DIR}/assets/romfs DESTINATION ${CMAKE_CURRENT_BINARY_DI # create assets target dkp_add_asset_target(sphaira_romfs ${CMAKE_CURRENT_BINARY_DIR}/romfs) -# add hbl exefs to romfs, used for forwarders -dkp_install_assets(sphaira_romfs - DESTINATION exefs - TARGETS - hbl_nso - hbl_npdm +# wait until hbl is built first as we need the exefs to embed +add_dependencies(sphaira hbl_nso hbl_npdm) + +# set the embed path for assets and hbl +target_compile_options(sphaira PRIVATE + --embed-dir=${CMAKE_SOURCE_DIR}/assets/embed + --embed-dir=${CMAKE_BINARY_DIR}/hbl ) # add nanovg shaders to romfs diff --git a/sphaira/include/app.hpp b/sphaira/include/app.hpp index 67be96c..b1348a5 100644 --- a/sphaira/include/app.hpp +++ b/sphaira/include/app.hpp @@ -69,6 +69,7 @@ public: static auto GetThemeIndex() -> s64; static auto GetDefaultImage() -> int; + static auto GetDefaultImageData() -> std::span; // returns argv[0] static auto GetExePath() -> fs::FsPath; @@ -196,6 +197,7 @@ public: static constexpr inline auto CONFIG_PATH = "/config/sphaira/config.ini"; static constexpr inline auto PLAYLOG_PATH = "/config/sphaira/playlog.ini"; static constexpr inline auto INI_SECTION = "config"; + static constexpr inline auto DEFAULT_THEME_PATH = "romfs:/themes/abyss_theme.ini"; fs::FsPath m_app_path; u64 m_start_timestamp{}; @@ -229,17 +231,18 @@ public: option::OptionBool m_hdd_enabled{INI_SECTION, "hdd_enabled", false}; option::OptionBool m_log_enabled{INI_SECTION, "log_enabled", false}; option::OptionBool m_replace_hbmenu{INI_SECTION, "replace_hbmenu", false}; + option::OptionString m_theme_path{INI_SECTION, "theme", DEFAULT_THEME_PATH}; option::OptionBool m_theme_music{INI_SECTION, "theme_music", true}; option::OptionBool m_12hour_time{INI_SECTION, "12hour_time", false}; option::OptionLong m_language{INI_SECTION, "language", 0}; // auto option::OptionString m_right_side_menu{INI_SECTION, "right_side_menu", "Appstore"}; + option::OptionBool m_progress_boost_mode{INI_SECTION, "progress_boost_mode", false}; // install options option::OptionBool m_install_sysmmc{INI_SECTION, "install_sysmmc", false}; option::OptionBool m_install_emummc{INI_SECTION, "install_emummc", false}; option::OptionBool m_install_sd{INI_SECTION, "install_sd", true}; option::OptionLong m_install_prompt{INI_SECTION, "install_prompt", true}; - option::OptionLong m_boost_mode{INI_SECTION, "boost_mode", false}; option::OptionBool m_allow_downgrade{INI_SECTION, "allow_downgrade", false}; option::OptionBool m_skip_if_already_installed{INI_SECTION, "skip_if_already_installed", true}; option::OptionBool m_ticket_only{INI_SECTION, "ticket_only", false}; diff --git a/sphaira/include/nro.hpp b/sphaira/include/nro.hpp index 5317477..01199a2 100644 --- a/sphaira/include/nro.hpp +++ b/sphaira/include/nro.hpp @@ -11,13 +11,17 @@ namespace sphaira { struct Hbini { u64 timestamp{}; // timestamp of last launch - u32 launch_count{}; // +}; + +struct MiniNacp { + NacpLanguageEntry lang; + char display_version[0x10]; }; struct NroEntry { fs::FsPath path{}; s64 size{}; - NacpStruct nacp{}; + MiniNacp nacp{}; u64 icon_size{}; u64 icon_offset{}; @@ -31,11 +35,11 @@ struct NroEntry { std::optional has_star{std::nullopt}; auto GetName() const -> const char* { - return nacp.lang[0].name; + return nacp.lang.name; } auto GetAuthor() const -> const char* { - return nacp.lang[0].author; + return nacp.lang.author; } auto GetDisplayVersion() const -> const char* { diff --git a/sphaira/include/option.hpp b/sphaira/include/option.hpp index 1625176..4eb6204 100644 --- a/sphaira/include/option.hpp +++ b/sphaira/include/option.hpp @@ -17,6 +17,11 @@ struct OptionBase { auto GetOr(const char* name) -> T; void Set(T value); + // returns true if loaded. + auto LoadFrom(const char* section, const char* name, const char* value) -> bool; + // same as above, but only checks the name. + auto LoadFrom(const char* name, const char* value) -> bool; + private: auto GetInternal(const char* name) -> T; diff --git a/sphaira/include/owo.hpp b/sphaira/include/owo.hpp index ed2a6f7..c180aa5 100644 --- a/sphaira/include/owo.hpp +++ b/sphaira/include/owo.hpp @@ -4,7 +4,6 @@ #include #include #include "ui/progress_box.hpp" -// #include namespace sphaira { @@ -15,12 +14,9 @@ struct OwoConfig { std::string author{}; NacpStruct nacp; std::vector icon; - std::vector main; - std::vector npdm; std::vector logo; std::vector gif; - // std::optional tid; std::vector program_nca{}; }; diff --git a/sphaira/include/ui/menus/homebrew.hpp b/sphaira/include/ui/menus/homebrew.hpp index 777edf1..685ef72 100644 --- a/sphaira/include/ui/menus/homebrew.hpp +++ b/sphaira/include/ui/menus/homebrew.hpp @@ -37,7 +37,7 @@ struct Menu final : grid::Menu { return m_entries; } - static Result InstallHomebrew(const fs::FsPath& path, const NacpStruct& nacp, const std::vector& icon); + static Result InstallHomebrew(const fs::FsPath& path, const std::vector& icon); static Result InstallHomebrewFromPath(const fs::FsPath& path); private: diff --git a/sphaira/include/yati/yati.hpp b/sphaira/include/yati/yati.hpp index 7404e04..27f41bb 100644 --- a/sphaira/include/yati/yati.hpp +++ b/sphaira/include/yati/yati.hpp @@ -70,10 +70,6 @@ enum : Result { struct Config { bool sd_card_install{}; - // sets the performance mode to FastLoad which boosts the CPU clock - // and lowers the GPU clock. - bool boost_mode{}; - // enables downgrading patch / data patch (dlc) version. bool allow_downgrade{}; diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index 6688691..e4893b2 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,10 @@ constexpr fs::FsPath DEFAULT_MUSIC_PATH = "/config/sphaira/themes/default_music. constexpr const char* DEFAULT_MUSIC_URL = "https://files.catbox.moe/1ovji1.bfstm"; // constexpr const char* DEFAULT_MUSIC_URL = "https://raw.githubusercontent.com/ITotalJustice/sphaira/refs/heads/master/assets/default_music.bfstm"; +constexpr const u8 DEFAULT_IMAGE_DATA[]{ + #embed +}; + void download_default_music() { App::Push(std::make_shared(0, "Downloading "_i18n, "default_music.bfstm", [](auto pbox){ const auto result = curl::Api().ToFile( @@ -444,10 +449,7 @@ void App::Loop() { // update timestamp ini_putl(nro_path.c_str(), "timestamp", timestamp, App::PLAYLOG_PATH); - // update launch_count - const long old_launch_count = ini_getl(nro_path.c_str(), "launch_count", 0, App::PLAYLOG_PATH); - ini_putl(nro_path.c_str(), "launch_count", old_launch_count + 1, App::PLAYLOG_PATH); - log_write("updating timestamp and launch count for: %s %lu %ld\n", nro_path.c_str(), timestamp, old_launch_count + 1); + log_write("updating timestamp for: %s %lu\n", nro_path.c_str(), timestamp); // force disable pop-back to main menu. __nx_applet_exit_mode = 0; @@ -516,11 +518,11 @@ auto App::Push(std::shared_ptr widget) -> void { } auto App::PopToMenu() -> void { - for (auto it = g_app->m_widgets.rbegin(); it != g_app->m_widgets.rend(); it++) { - const auto& p = *it; + for (auto& p : std::ranges::views::reverse(g_app->m_widgets)) { if (p->IsMenu()) { break; } + p->SetPop(); } } @@ -595,6 +597,10 @@ auto App::GetDefaultImage() -> int { return g_app->m_default_image; } +auto App::GetDefaultImageData() -> std::span { + return DEFAULT_IMAGE_DATA; +} + auto App::GetExePath() -> fs::FsPath { return g_app->m_app_path; } @@ -868,18 +874,7 @@ void App::SetTextScrollSpeed(long index) { } auto App::Install(OwoConfig& config) -> Result { - R_TRY(romfsInit()); - ON_SCOPE_EXIT(romfsExit()); - - std::vector main_data, npdm_data, logo_data, gif_data; - R_TRY(fs::read_entire_file("romfs:/exefs/main", main_data)); - R_TRY(fs::read_entire_file("romfs:/exefs/main.npdm", npdm_data)); - config.nro_path = nro_add_arg_file(config.nro_path); - config.main = main_data; - config.npdm = npdm_data; - config.logo = logo_data; - config.gif = gif_data; if (!config.icon.empty()) { config.icon = GetNroIcon(config.icon); } @@ -898,18 +893,7 @@ auto App::Install(OwoConfig& config) -> Result { } auto App::Install(ui::ProgressBox* pbox, OwoConfig& config) -> Result { - R_TRY(romfsInit()); - ON_SCOPE_EXIT(romfsExit()); - - std::vector main_data, npdm_data, logo_data, gif_data; - R_TRY(fs::read_entire_file("romfs:/exefs/main", main_data)); - R_TRY(fs::read_entire_file("romfs:/exefs/main.npdm", npdm_data)); - config.nro_path = nro_add_arg_file(config.nro_path); - config.main = main_data; - config.npdm = npdm_data; - config.logo = logo_data; - config.gif = gif_data; if (!config.icon.empty()) { config.icon = GetNroIcon(config.icon); } @@ -1268,6 +1252,9 @@ void App::ScanThemeEntries() { App::App(const char* argv0) { TimeStamp ts; + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + g_app = this; m_start_timestamp = armGetSystemTick(); if (!std::strncmp(argv0, "sdmc:/", 6)) { @@ -1283,10 +1270,55 @@ App::App(const char* argv0) { } fs::FsNativeSd fs; - fs.CreateDirectoryRecursively("/config/sphaira/assoc"); - fs.CreateDirectoryRecursively("/config/sphaira/themes"); - fs.CreateDirectoryRecursively("/config/sphaira/github"); - fs.CreateDirectoryRecursively("/config/sphaira/i18n"); + fs.CreateDirectoryRecursively("/config/sphaira"); + fs.CreateDirectory("/config/sphaira/assoc"); + fs.CreateDirectory("/config/sphaira/themes"); + fs.CreateDirectory("/config/sphaira/github"); + fs.CreateDirectory("/config/sphaira/i18n"); + + auto cb = [](const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, void *UserData) -> int { + auto app = static_cast(UserData); + + if (!std::strcmp(Section, INI_SECTION)) { + if (app->m_nxlink_enabled.LoadFrom(Key, Value)) {} + else if (app->m_mtp_enabled.LoadFrom(Key, Value)) {} + else if (app->m_ftp_enabled.LoadFrom(Key, Value)) {} + else if (app->m_hdd_enabled.LoadFrom(Key, Value)) {} + else if (app->m_log_enabled.LoadFrom(Key, Value)) {} + else if (app->m_replace_hbmenu.LoadFrom(Key, Value)) {} + else if (app->m_theme_path.LoadFrom(Key, Value)) {} + else if (app->m_theme_music.LoadFrom(Key, Value)) {} + else if (app->m_12hour_time.LoadFrom(Key, Value)) {} + else if (app->m_language.LoadFrom(Key, Value)) {} + else if (app->m_right_side_menu.LoadFrom(Key, Value)) {} + else if (app->m_install_sysmmc.LoadFrom(Key, Value)) {} + else if (app->m_install_emummc.LoadFrom(Key, Value)) {} + else if (app->m_install_sd.LoadFrom(Key, Value)) {} + else if (app->m_install_prompt.LoadFrom(Key, Value)) {} + else if (app->m_progress_boost_mode.LoadFrom(Key, Value)) {} + else if (app->m_allow_downgrade.LoadFrom(Key, Value)) {} + else if (app->m_skip_if_already_installed.LoadFrom(Key, Value)) {} + else if (app->m_ticket_only.LoadFrom(Key, Value)) {} + else if (app->m_skip_base.LoadFrom(Key, Value)) {} + else if (app->m_skip_patch.LoadFrom(Key, Value)) {} + else if (app->m_skip_addon.LoadFrom(Key, Value)) {} + else if (app->m_skip_data_patch.LoadFrom(Key, Value)) {} + else if (app->m_skip_ticket.LoadFrom(Key, Value)) {} + else if (app->m_skip_nca_hash_verify.LoadFrom(Key, Value)) {} + else if (app->m_skip_rsa_header_fixed_key_verify.LoadFrom(Key, Value)) {} + else if (app->m_skip_rsa_npdm_fixed_key_verify.LoadFrom(Key, Value)) {} + else if (app->m_ignore_distribution_bit.LoadFrom(Key, Value)) {} + else if (app->m_convert_to_standard_crypto.LoadFrom(Key, Value)) {} + else if (app->m_lower_master_key.LoadFrom(Key, Value)) {} + else if (app->m_lower_system_version.LoadFrom(Key, Value)) {} + } + + return 1; + }; + + // load all configs ahead of time, as this is actually faster than + // loading each config one by one as it avoids re-opening the file multiple times. + ini_browse(cb, this, CONFIG_PATH); if (App::GetLogEnable()) { log_file_init(); @@ -1409,17 +1441,14 @@ App::App(const char* argv0) { ScanThemeEntries(); - fs::FsPath theme_path{}; - constexpr fs::FsPath default_theme_path{"romfs:/themes/abyss_theme.ini"}; - ini_gets("config", "theme", default_theme_path, theme_path, sizeof(theme_path), CONFIG_PATH); - // try and load previous theme, default to previous version otherwise. + fs::FsPath theme_path = m_theme_path.Get(); ThemeMeta theme_meta; if (R_SUCCEEDED(romfsInit())) { ON_SCOPE_EXIT(romfsExit()); if (!LoadThemeMeta(theme_path, theme_meta)) { log_write("failed to load meta using default\n"); - theme_path = default_theme_path; + theme_path = DEFAULT_THEME_PATH; LoadThemeMeta(theme_path, theme_meta); } } @@ -1456,20 +1485,12 @@ App::App(const char* argv0) { } ini_putl(GetExePath(), "timestamp", m_start_timestamp, App::PLAYLOG_PATH); - const long old_launch_count = ini_getl(GetExePath(), "launch_count", 0, App::PLAYLOG_PATH); - ini_putl(GetExePath(), "launch_count", old_launch_count + 1, App::PLAYLOG_PATH); // 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()); - } - } + m_default_image = nvgCreateImageMem(vg, 0, DEFAULT_IMAGE_DATA, std::size(DEFAULT_IMAGE_DATA)); App::Push(std::make_shared()); - log_write("finished app constructor, time taken: %.2fs %zums\n", ts.GetSecondsD(), ts.GetMs()); + log_write("\n\tfinished app constructor, time taken: %.2fs %zums\n\n", ts.GetSecondsD(), ts.GetMs()); } void App::PlaySoundEffect(SoundEffect effect) { @@ -1588,6 +1609,10 @@ void App::DisplayAdvancedOptions(bool left_side) { App::SetReplaceHbmenuEnable(enable); })); + options->Add(std::make_shared("Boost CPU during transfer"_i18n, App::GetApp()->m_progress_boost_mode.Get(), [](bool& enable){ + App::GetApp()->m_progress_boost_mode.Set(enable); + })); + options->Add(std::make_shared("Text scroll speed"_i18n, text_scroll_speed_items, [](s64& index_out){ App::SetTextScrollSpeed(index_out); }, App::GetTextScrollSpeed())); @@ -1637,10 +1662,6 @@ void App::DisplayInstallOptions(bool left_side) { App::SetInstallSdEnable(index_out); }, (s64)App::GetInstallSdEnable())); - options->Add(std::make_shared("Boost CPU clock"_i18n, App::GetApp()->m_boost_mode.Get(), [](bool& enable){ - App::GetApp()->m_boost_mode.Set(enable); - })); - options->Add(std::make_shared("Allow downgrade"_i18n, App::GetApp()->m_allow_downgrade.Get(), [](bool& enable){ App::GetApp()->m_allow_downgrade.Set(enable); })); @@ -1724,6 +1745,9 @@ void App::DisplayDumpOptions(bool left_side) { } App::~App() { + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + log_write("starting to exit\n"); i18n::exit(); diff --git a/sphaira/source/dumper.cpp b/sphaira/source/dumper.cpp index cb56941..61308ed 100644 --- a/sphaira/source/dumper.cpp +++ b/sphaira/source/dumper.cpp @@ -106,13 +106,14 @@ private: Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, BaseSource* source, std::span paths) { constexpr s64 BIG_FILE_SIZE = 1024ULL*1024ULL*1024ULL*4ULL; - for (auto path : paths) { + for (const auto& path : paths) { + const auto base_path = fs::AppendPath(root, path); const auto file_size = source->GetSize(path); pbox->SetImage(source->GetIcon(path)); pbox->SetTitle(source->GetName(path)); - pbox->NewTransfer(path); + pbox->NewTransfer(base_path); - const auto temp_path = fs::AppendPath(root, path + ".temp"); + const auto temp_path = base_path + ".temp"; fs->CreateDirectoryRecursivelyWithPath(temp_path); fs->DeleteFile(temp_path); @@ -135,9 +136,8 @@ Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, Bas )); } - path = fs::AppendPath(root, path); - fs->DeleteFile(path); - R_TRY(fs->RenameFile(temp_path, path)); + fs->DeleteFile(base_path); + R_TRY(fs->RenameFile(temp_path, base_path)); } R_SUCCEED(); diff --git a/sphaira/source/nro.cpp b/sphaira/source/nro.cpp index 6833d1a..6abde12 100644 --- a/sphaira/source/nro.cpp +++ b/sphaira/source/nro.cpp @@ -56,21 +56,21 @@ auto nro_parse_internal(fs::FsNative& fs, const fs::FsPath& path, NroEntry& entr // R_UNLESS(asset.magic == NROASSETHEADER_MAGIC, NroError_BadMagic); // some .nro (vgedit) have bad nacp, fake the nacp - if (asset.magic != NROASSETHEADER_MAGIC || asset.nacp.offset == 0 || asset.nacp.size != sizeof(entry.nacp)) { + auto& nacp = entry.nacp; + if (asset.magic != NROASSETHEADER_MAGIC || asset.nacp.offset == 0 || asset.nacp.size != sizeof(NacpStruct)) { std::memset(&asset, 0, sizeof(asset)); - std::memset(&entry.nacp, 0, sizeof(entry.nacp)); + std::memset(&nacp, 0, sizeof(nacp)); // get the name without the .nro const auto file_name = std::strrchr(path, '/') + 1; const auto file_name_len = std::strlen(file_name); - for (auto& lang : entry.nacp.lang) { - std::strncpy(lang.name, file_name, file_name_len - 4); - std::strcpy(lang.author, "Unknown"); - } - std::strcpy(entry.nacp.display_version, "Unknown"); + std::strncpy(nacp.lang.name, file_name, file_name_len - 4); + std::strcpy(nacp.lang.author, "Unknown"); + std::strcpy(nacp.display_version, "Unknown"); entry.is_nacp_valid = false; } else { - R_TRY(fsFileRead(&f, data.header.size + asset.nacp.offset, &entry.nacp, sizeof(entry.nacp), FsReadOption_None, &bytes_read)); + R_TRY(fsFileRead(&f, data.header.size + asset.nacp.offset, &nacp.lang, sizeof(nacp.lang), FsReadOption_None, &bytes_read)); + R_TRY(fsFileRead(&f, data.header.size + asset.nacp.offset + offsetof(NacpStruct, display_version), nacp.display_version, sizeof(nacp.display_version), FsReadOption_None, &bytes_read)); entry.is_nacp_valid = true; } diff --git a/sphaira/source/option.cpp b/sphaira/source/option.cpp index 2286c84..6d2a093 100644 --- a/sphaira/source/option.cpp +++ b/sphaira/source/option.cpp @@ -3,7 +3,33 @@ #include "option.hpp" #include "app.hpp" +#include +#include +#include + namespace sphaira::option { +namespace { + +// these are taken from minini in order to parse a value already loaded in memory. +long getl(const char* LocalBuffer, long def) { + const auto len = strlen(LocalBuffer); + return (len == 0) ? def + : ((len >= 2 && toupper((int)LocalBuffer[1]) == 'X') ? strtol(LocalBuffer, NULL, 16) + : strtol(LocalBuffer, NULL, 10)); +} + +bool getbool(const char* LocalBuffer, bool def) { + const auto c = toupper(LocalBuffer[0]); + + if (c == 'Y' || c == '1' || c == 'T') + return true; + else if (c == 'N' || c == '0' || c == 'F') + return false; + else + return def; +} + +} // namespace template auto OptionBase::GetInternal(const char* name) -> T { @@ -47,6 +73,28 @@ void OptionBase::Set(T value) { } } +template +auto OptionBase::LoadFrom(const char* section, const char* name, const char* value) -> bool { + return m_section == section && LoadFrom(name, value); +} + +template +auto OptionBase::LoadFrom(const char* name, const char* value) -> bool { + if (m_name == name) { + if constexpr(std::is_same_v) { + m_value = getbool(value, m_default_value); + } else if constexpr(std::is_same_v) { + m_value = getl(value, m_default_value); + } else if constexpr(std::is_same_v) { + m_value = value; + } + + return true; + } + + return false; +} + template struct OptionBase; template struct OptionBase; template struct OptionBase; diff --git a/sphaira/source/owo.cpp b/sphaira/source/owo.cpp index 4a0d40d..597f613 100644 --- a/sphaira/source/owo.cpp +++ b/sphaira/source/owo.cpp @@ -34,6 +34,14 @@ constexpr u32 PFS0_PADDING_SIZE = 0x200; constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF; constexpr u32 ROMFS_FILEPARTITION_OFS = 0x200; +constexpr const u8 HBL_MAIN_DATA[]{ + #embed +}; + +constexpr const u8 HBL_NPDM_DATA[]{ + #embed +}; + // stdio-like wrapper for std::vector struct BufHelper { BufHelper() = default; @@ -831,6 +839,9 @@ auto create_meta_nca(u64 tid, const keys::Keys& keys, NcmStorageId storage_id, c } auto install_forwader_internal(ui::ProgressBox* pbox, OwoConfig& config, NcmStorageId storage_id) -> Result { + pbox->SetTitle(config.name); + pbox->SetImageDataConst(config.icon); + R_UNLESS(!config.nro_path.empty(), OwoError_BadArgs); // R_UNLESS(!config.icon.empty(), OwoError_BadArgs); @@ -864,13 +875,10 @@ auto install_forwader_internal(ui::ProgressBox* pbox, OwoConfig& config, NcmStor // create program if (config.program_nca.empty()) { - R_UNLESS(!config.main.empty(), OwoError_BadArgs); - R_UNLESS(!config.npdm.empty(), OwoError_BadArgs); - pbox->NewTransfer("Creating Program"_i18n).UpdateTransfer(0, 8); FileEntries exefs; - add_file_entry(exefs, "main", config.main); - add_file_entry(exefs, "main.npdm", config.npdm); + add_file_entry(exefs, "main", HBL_MAIN_DATA); + add_file_entry(exefs, "main.npdm", HBL_NPDM_DATA); FileEntries romfs; add_file_entry(romfs, "/nextArgv", config.args.data(), config.args.length()); diff --git a/sphaira/source/ui/menus/appstore.cpp b/sphaira/source/ui/menus/appstore.cpp index fea1e1a..70a8e6d 100644 --- a/sphaira/source/ui/menus/appstore.cpp +++ b/sphaira/source/ui/menus/appstore.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,22 @@ constexpr auto URL_JSON = "https://switch.cdn.fortheusers.org/repo.json"; constexpr auto URL_POST_FEEDBACK = "http://switchbru.com/appstore/feedback"; constexpr auto URL_GET_FEEDACK = "http://switchbru.com/appstore/feedback"; +constexpr const u8 UPDATE_IMAGE_DATA[]{ + #embed +}; + +constexpr const u8 GET_IMAGE_DATA[]{ + #embed +}; + +constexpr const u8 LOCAL_IMAGE_DATA[]{ + #embed +}; + +constexpr const u8 INSTALLED_IMAGE_DATA[]{ + #embed +}; + constexpr const char* FILTER_STR[] = { "All", "Games", @@ -172,7 +189,7 @@ auto LoadAndParseManifest(const Entry& e) -> ManifestEntries { return ParseManifest(std::span{(const char*)data.data(), data.size()}); } -auto EntryLoadImageFile(fs::Fs& fs, const fs::FsPath& path, LazyImage& image) -> bool { +auto EntryLoadImageData(std::span image_buf, LazyImage& image) -> bool { // already have the image if (image.image) { // log_write("warning, tried to load image: %s when already loaded\n", path); @@ -180,17 +197,29 @@ auto EntryLoadImageFile(fs::Fs& fs, const fs::FsPath& path, LazyImage& image) -> } auto vg = App::GetVg(); + int channels_in_file; + auto buf = stbi_load_from_memory(image_buf.data(), image_buf.size(), &image.w, &image.h, &channels_in_file, 4); + if (buf) { + ON_SCOPE_EXIT(stbi_image_free(buf)); + std::memcpy(image.first_pixel, buf, sizeof(image.first_pixel)); + image.image = nvgCreateImageRGBA(vg, image.w, image.h, 0, buf); + } + + return image.image; +} + +auto EntryLoadImageFile(fs::Fs& fs, const fs::FsPath& path, LazyImage& image) -> bool { + // already have the image + if (image.image) { + // log_write("warning, tried to load image: %s when already loaded\n", path); + return true; + } + std::vector image_buf; if (R_FAILED(fs.read_entire_file(path, image_buf))) { log_write("failed to load image from file: %s\n", path.s); } else { - int channels_in_file; - auto buf = stbi_load_from_memory(image_buf.data(), image_buf.size(), &image.w, &image.h, &channels_in_file, 4); - if (buf) { - ON_SCOPE_EXIT(stbi_image_free(buf)); - std::memcpy(image.first_pixel, buf, sizeof(image.first_pixel)); - image.image = nvgCreateImageRGBA(vg, image.w, image.h, 0, buf); - } + EntryLoadImageData(image_buf, image); } if (!image.image) { @@ -311,7 +340,7 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> Result { // remove directory, this will also delete manifest and info const auto dir = BuildPackageCachePath(entry); - pbox->NewTransfer("Removing "_i18n + dir); + pbox->NewTransfer("Removing "_i18n + dir.toString()); if (R_FAILED(fs.DeleteDirectoryRecursively(dir))) { log_write("failed to delete folder: %s\n", dir.s); } else { @@ -329,7 +358,7 @@ auto UninstallApp(ProgressBox* pbox, const Entry& entry) -> Result { // 4. move everything from placeholder to normal location auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result { static const fs::FsPath zip_out{"/switch/sphaira/cache/appstore/temp.zip"}; - constexpr auto chunk_size = 1024 * 512; // 512KiB + std::vector buf(1024 * 512); // 512KiB fs::FsNativeSd fs; R_TRY(fs.GetFsOpenResult()); @@ -405,26 +434,7 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result { } } - const auto unzip_to = [pbox, &fs, zfile](const fs::FsPath& inzip, fs::FsPath output) -> Result { - pbox->NewTransfer(inzip); - - if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) { - log_write("failed to find %s\n", inzip.s); - R_THROW(0x1); - } - - if (UNZ_OK != unzOpenCurrentFile(zfile)) { - log_write("failed to open current file\n"); - R_THROW(0x1); - } - ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); - - unz_file_info64 info; - if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, 0, 0, 0, 0, 0, 0)) { - log_write("failed to get current info\n"); - R_THROW(0x1); - } - + const auto unzip_to_file = [&](const unz_file_info64& info, const fs::FsPath& inzip, fs::FsPath output) -> Result { if (output[0] != '/') { output = fs::AppendPath("/", output); } @@ -444,7 +454,6 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result { R_TRY(fsFileSetSize(&f, info.uncompressed_size)); - std::vector buf(chunk_size); u64 offset{}; while (offset < info.uncompressed_size) { R_TRY(pbox->ShouldExitResult()); @@ -464,37 +473,106 @@ auto InstallApp(ProgressBox* pbox, const Entry& entry) -> Result { R_SUCCEED(); }; - // unzip manifest and info - R_TRY(unzip_to("info.json", BuildInfoCachePath(entry))); - R_TRY(unzip_to("manifest.install", BuildManifestCachePath(entry))); + const auto unzip_to = [&](const fs::FsPath& inzip, const fs::FsPath& output) -> Result { + pbox->NewTransfer(inzip); - for (auto& new_entry : new_manifest) { - R_TRY(pbox->ShouldExitResult()); - - switch (new_entry.command) { - case 'E': // both are the same? - case 'U': - break; - - case 'G': { // checks if file exists, if not, extract - if (fs.FileExists(fs::AppendPath("/", new_entry.path))) { - continue; - } - } break; - - default: - log_write("bad command: %c\n", new_entry.command); - continue; + if (UNZ_END_OF_LIST_OF_FILE == unzLocateFile(zfile, inzip, 0)) { + log_write("failed to find %s\n", inzip.s); + R_THROW(0x1); } - R_TRY(unzip_to(new_entry.path, new_entry.path)); - } + if (UNZ_OK != unzOpenCurrentFile(zfile)) { + log_write("failed to open current file\n"); + R_THROW(0x1); + } + ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); + + unz_file_info64 info; + if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, 0, 0, 0, 0, 0, 0)) { + log_write("failed to get current info\n"); + R_THROW(0x1); + } + + return unzip_to_file(info, inzip, output); + }; + + const auto unzip_all = [&](std::span entries) -> Result { + unz_global_info64 ginfo; + if (UNZ_OK != unzGetGlobalInfo64(zfile, &ginfo)) { + R_THROW(0x1); + } + + if (UNZ_OK != unzGoToFirstFile(zfile)) { + R_THROW(0x1); + } + + for (s64 i = 0; i < ginfo.number_entry; i++) { + R_TRY(pbox->ShouldExitResult()); + + if (i > 0) { + if (UNZ_OK != unzGoToNextFile(zfile)) { + log_write("failed to unzGoToNextFile\n"); + R_THROW(0x1); + } + } + + if (UNZ_OK != unzOpenCurrentFile(zfile)) { + log_write("failed to open current file\n"); + R_THROW(0x1); + } + ON_SCOPE_EXIT(unzCloseCurrentFile(zfile)); + + unz_file_info64 info; + char name[512]; + if (UNZ_OK != unzGetCurrentFileInfo64(zfile, &info, name, sizeof(name), 0, 0, 0, 0)) { + log_write("failed to get current info\n"); + R_THROW(0x1); + } + + const auto it = std::ranges::find_if(entries, [&name](auto& e){ + return !strcasecmp(name, e.path); + }); + + if (it == entries.end()) [[unlikely]] { + continue; + } + + pbox->NewTransfer(it->path); + + switch (it->command) { + case 'E': // both are the same? + case 'U': + break; + + case 'G': { // checks if file exists, if not, extract + if (fs.FileExists(fs::AppendPath("/", it->path))) { + continue; + } + } break; + + default: + log_write("bad command: %c\n", it->command); + continue; + } + + R_TRY(unzip_to_file(info, it->path, it->path)); + } + + R_SUCCEED(); + }; + + // unzip manifest, info and all entries. + TimeStamp ts; + R_TRY(unzip_to("info.json", BuildInfoCachePath(entry))); + R_TRY(unzip_to("manifest.install", BuildManifestCachePath(entry))); + R_TRY(unzip_all(new_manifest)); + log_write("\n\t[APPSTORE] finished extract new, time taken: %.2fs %zums\n\n", ts.GetSecondsD(), ts.GetMs()); // finally finally, remove files no longer in the manifest for (auto& old_entry : old_manifest) { bool found = false; for (auto& new_entry : new_manifest) { - if (!std::strcmp(old_entry.path, new_entry.path)) { + if (!strcasecmp(old_entry.path, new_entry.path)) { found = true; break; } @@ -1022,14 +1100,11 @@ void Menu::OnFocusGained() { // log_write("saying we got focus base: size: %zu count: %zu\n", repo_json.size(), m_entries.size()); if (!m_default_image.image) { - if (R_SUCCEEDED(romfsInit())) { - ON_SCOPE_EXIT(romfsExit()); - EntryLoadImageFile("romfs:/default.png", m_default_image); - EntryLoadImageFile("romfs:/UPDATE.png", m_update); - EntryLoadImageFile("romfs:/GET.png", m_get); - EntryLoadImageFile("romfs:/LOCAL.png", m_local); - EntryLoadImageFile("romfs:/INSTALLED.png", m_installed); - } + EntryLoadImageData(App::GetDefaultImageData(), m_default_image); + EntryLoadImageData(UPDATE_IMAGE_DATA, m_update); + EntryLoadImageData(GET_IMAGE_DATA, m_get); + EntryLoadImageData(LOCAL_IMAGE_DATA, m_local); + EntryLoadImageData(INSTALLED_IMAGE_DATA, m_installed); } if (m_entries.empty()) { @@ -1074,6 +1149,9 @@ void Menu::SetIndex(s64 index) { } void Menu::ScanHomebrew() { + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + from_json(REPO_PATH, m_entries); fs::FsNativeSd fs; diff --git a/sphaira/source/ui/menus/filebrowser.cpp b/sphaira/source/ui/menus/filebrowser.cpp index b4765d5..8961a2c 100644 --- a/sphaira/source/ui/menus/filebrowser.cpp +++ b/sphaira/source/ui/menus/filebrowser.cpp @@ -941,6 +941,9 @@ void FsView::InstallForwarder() { log_write("parsing nro\n"); R_TRY(nro_parse(assoc.path, nro)); + NacpStruct nacp; + R_TRY(nro_get_nacp(assoc.path, nacp)); + log_write("got nro data\n"); auto file_name = assoc.use_base_name ? GetEntry().GetName() : GetEntry().GetInternalName(); @@ -955,9 +958,9 @@ void FsView::InstallForwarder() { OwoConfig config{}; config.nro_path = assoc.path.toString(); config.args = nro_add_arg_file(GetNewPathCurrent()); - config.name = nro.nacp.lang[0].name + std::string{" | "} + file_name; + config.name = nro.nacp.lang.name + std::string{" | "} + file_name; // config.name = file_name; - config.nacp = nro.nacp; + config.nacp = nacp; config.icon = GetRomIcon(m_fs.get(), pbox, file_name, db_indexs, nro); pbox->SetImageDataConst(config.icon); @@ -1017,7 +1020,7 @@ void FsView::UnzipFiles(fs::FsPath dir_path) { R_THROW(0x1); } - for (int i = 0; i < pglobal_info.number_entry; i++) { + for (s64 i = 0; i < pglobal_info.number_entry; i++) { if (i > 0) { if (UNZ_OK != unzGoToNextFile(zfile)) { log_write("failed to unzGoToNextFile\n"); @@ -1325,6 +1328,9 @@ void FsView::UploadFiles() { } auto FsView::Scan(const fs::FsPath& new_path, bool is_walk_up) -> Result { + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + log_write("new scan path: %s\n", new_path.s); if (!is_walk_up && !m_path.empty() && !m_entries_current.empty()) { const LastFile f(GetEntry().name, m_index, m_list->GetYoff(), m_entries_current.size()); @@ -1781,7 +1787,7 @@ static Result DeleteAllCollections(ProgressBox* pbox, fs::Fs* fs, const Selected const auto full_path = FsView::GetNewPath(c.path, p.name); pbox->SetTitle(p.name); - pbox->NewTransfer("Deleting "_i18n + full_path); + pbox->NewTransfer("Deleting "_i18n + full_path.toString()); if ((mode & FsDirOpenMode_ReadDirs) && p.type == FsDirEntryType_Dir) { log_write("deleting dir: %s\n", full_path.s); R_TRY(fs->DeleteDirectory(full_path)); @@ -1804,7 +1810,7 @@ static Result DeleteAllCollections(ProgressBox* pbox, fs::Fs* fs, const Selected const auto full_path = FsView::GetNewPath(selected.m_path, p.name); pbox->SetTitle(p.name); - pbox->NewTransfer("Deleting "_i18n + full_path); + pbox->NewTransfer("Deleting "_i18n + full_path.toString()); if ((mode & FsDirOpenMode_ReadDirs) && p.type == FsDirEntryType_Dir) { log_write("deleting dir: %s\n", full_path.s); diff --git a/sphaira/source/ui/menus/game_menu.cpp b/sphaira/source/ui/menus/game_menu.cpp index fa6dbc2..f9aedf7 100644 --- a/sphaira/source/ui/menus/game_menu.cpp +++ b/sphaira/source/ui/menus/game_menu.cpp @@ -981,6 +981,9 @@ void Menu::ScanHomebrew() { const auto hide_forwarders = m_hide_forwarders.Get(); TimeStamp ts; + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + FreeEntries(); m_entries.reserve(ENTRY_CHUNK_COUNT); diff --git a/sphaira/source/ui/menus/gc_menu.cpp b/sphaira/source/ui/menus/gc_menu.cpp index 846dc57..6bb4609 100644 --- a/sphaira/source/ui/menus/gc_menu.cpp +++ b/sphaira/source/ui/menus/gc_menu.cpp @@ -953,6 +953,9 @@ void Menu::OnChangeIndex(s64 new_index) { } Result Menu::DumpGames(u32 flags) { + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + R_TRY(GcMountStorage()); u32 location_flags = dump::DumpLocationFlag_All; diff --git a/sphaira/source/ui/menus/homebrew.cpp b/sphaira/source/ui/menus/homebrew.cpp index 216f355..4008c59 100644 --- a/sphaira/source/ui/menus/homebrew.cpp +++ b/sphaira/source/ui/menus/homebrew.cpp @@ -233,7 +233,7 @@ void Menu::SetIndex(s64 index) { void Menu::InstallHomebrew() { const auto& nro = m_entries[m_index]; - InstallHomebrew(nro.path, nro.nacp, nro_get_icon(nro.path, nro.icon_size, nro.icon_offset)); + InstallHomebrew(nro.path, nro_get_icon(nro.path, nro.icon_size, nro.icon_offset)); } void Menu::ScanHomebrew() { @@ -266,8 +266,6 @@ void Menu::ScanHomebrew() { if (user->ini) { if (!strcmp(Key, "timestamp")) { user->ini->timestamp = atoi(Value); - } else if (!strcmp(Key, "launch_count")) { - user->ini->launch_count = atoi(Value); } } @@ -412,19 +410,16 @@ void Menu::OnLayoutChange() { grid::Menu::OnLayoutChange(m_list, m_layout.Get()); } -Result Menu::InstallHomebrew(const fs::FsPath& path, const NacpStruct& nacp, const std::vector& icon) { +Result Menu::InstallHomebrew(const fs::FsPath& path, const std::vector& icon) { OwoConfig config{}; config.nro_path = path.toString(); - config.nacp = nacp; + R_TRY(nro_get_nacp(path, config.nacp)); config.icon = icon; return App::Install(config); } Result Menu::InstallHomebrewFromPath(const fs::FsPath& path) { - NacpStruct nacp; - R_TRY(nro_get_nacp(path, nacp)) - const auto icon = nro_get_icon(path); - return InstallHomebrew(path, nacp, icon); + return InstallHomebrew(path, nro_get_icon(path)); } } // namespace sphaira::ui::menu::homebrew diff --git a/sphaira/source/ui/menus/themezer.cpp b/sphaira/source/ui/menus/themezer.cpp index 5d3385c..20f4e59 100644 --- a/sphaira/source/ui/menus/themezer.cpp +++ b/sphaira/source/ui/menus/themezer.cpp @@ -647,6 +647,9 @@ void Menu::PackListDownload() { curl::Flags{curl::Flag_Cache}, curl::StopToken{this->GetToken()}, curl::OnComplete{[this, page_index](auto& result){ + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + ON_SCOPE_EXIT(appletSetCpuBoostMode(ApmCpuBoostMode_Normal)); + log_write("got themezer data\n"); if (!result.success) { auto& page = m_pages[page_index-1]; diff --git a/sphaira/source/ui/progress_box.cpp b/sphaira/source/ui/progress_box.cpp index 2fd68d9..71ff1eb 100644 --- a/sphaira/source/ui/progress_box.cpp +++ b/sphaira/source/ui/progress_box.cpp @@ -19,6 +19,10 @@ void threadFunc(void* arg) { } // namespace ProgressBox::ProgressBox(int image, const std::string& action, const std::string& title, ProgressBoxCallback callback, ProgressBoxDoneCallback done, int cpuid, int prio, int stack_size) { + if (App::GetApp()->m_progress_boost_mode.Get()) { + appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); + } + SetAction(Button::B, Action{"Back"_i18n, [this](){ App::Push(std::make_shared("Are you sure you wish to cancel?"_i18n, "No"_i18n, "Yes"_i18n, 1, [this](auto op_index){ if (op_index && *op_index) { @@ -61,6 +65,8 @@ ProgressBox::~ProgressBox() { FreeImage(); m_done(m_thread_data.result); + + appletSetCpuBoostMode(ApmCpuBoostMode_Normal); } auto ProgressBox::Update(Controller* controller, TouchInfo* touch) -> void { diff --git a/sphaira/source/yati/yati.cpp b/sphaira/source/yati/yati.cpp index d8f27d8..02d0175 100644 --- a/sphaira/source/yati/yati.cpp +++ b/sphaira/source/yati/yati.cpp @@ -767,16 +767,11 @@ Yati::~Yati() { ncmContentStorageClose(std::addressof(ncm_cs[i])); } - if (config.boost_mode) { - appletSetCpuBoostMode(ApmCpuBoostMode_Normal); - } - App::SetAutoSleepDisabled(false); } Result Yati::Setup(const ConfigOverride& override) { config.sd_card_install = override.sd_card_install.value_or(App::GetApp()->m_install_sd.Get()); - config.boost_mode = App::GetApp()->m_boost_mode.Get(); config.allow_downgrade = App::GetApp()->m_allow_downgrade.Get(); config.skip_if_already_installed = App::GetApp()->m_skip_if_already_installed.Get(); config.ticket_only = App::GetApp()->m_ticket_only.Get(); @@ -794,10 +789,6 @@ Result Yati::Setup(const ConfigOverride& override) { config.lower_system_version = override.lower_system_version.value_or(App::GetApp()->m_lower_system_version.Get()); storage_id = config.sd_card_install ? NcmStorageId_SdCard : NcmStorageId_BuiltInUser; - if (config.boost_mode) { - appletSetCpuBoostMode(ApmCpuBoostMode_FastLoad); - } - R_TRY(source->GetOpenResult()); R_TRY(splCryptoInitialize()); R_TRY(nsInitialize());