From 5edc3869cd32fc13d850e8f5f94a21fd86170f83 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Sun, 21 Sep 2025 18:54:08 +0100 Subject: [PATCH] display storage sizes, properly colour info text, and more (see below) - display internal and sd card storage sizes. - removed battery info. - removed current time info. - fix dumping save to sd card due to not opening the file with append. - change all sizes to display GB instead of GiB. - change progress bar units to 1000 rather than 1024. - all info text, such as sizes and timestamps now use the info text colouring. - shorten the ncm content type names. --- sphaira/include/app.hpp | 3 + sphaira/include/ui/menus/menu_base.hpp | 6 +- sphaira/include/utils/utils.hpp | 7 ++ sphaira/source/app.cpp | 14 ++++ sphaira/source/dumper.cpp | 2 +- sphaira/source/main.cpp | 3 - sphaira/source/ui/menus/appstore.cpp | 4 +- sphaira/source/ui/menus/filebrowser.cpp | 16 ++--- sphaira/source/ui/menus/game_meta_menu.cpp | 12 ++-- sphaira/source/ui/menus/game_nca_menu.cpp | 11 +--- sphaira/source/ui/menus/ghdl.cpp | 2 +- sphaira/source/ui/menus/grid_menu_base.cpp | 7 +- sphaira/source/ui/menus/menu_base.cpp | 74 +++++++++++++++++----- sphaira/source/ui/progress_box.cpp | 13 +--- sphaira/source/utils/utils.cpp | 27 ++++++++ sphaira/source/yati/nx/ncm.cpp | 6 +- 16 files changed, 139 insertions(+), 68 deletions(-) diff --git a/sphaira/include/app.hpp b/sphaira/include/app.hpp index fc40375..a99721b 100644 --- a/sphaira/include/app.hpp +++ b/sphaira/include/app.hpp @@ -155,6 +155,9 @@ public: static Result SetDefaultBackgroundMusic(fs::Fs* fs, const fs::FsPath& path); static void SetBackgroundMusicPause(bool pause); + static Result GetSdSize(s64* free, s64* total); + static Result GetEmmcSize(s64* free, s64* total); + // helper that converts 1.2.3 to a u32 used for comparisons. static auto GetVersionFromString(const char* str) -> u32; static auto IsVersionNewer(const char* current, const char* new_version) -> u32; diff --git a/sphaira/include/ui/menus/menu_base.hpp b/sphaira/include/ui/menus/menu_base.hpp index 8d28f77..c8c2470 100644 --- a/sphaira/include/ui/menus/menu_base.hpp +++ b/sphaira/include/ui/menus/menu_base.hpp @@ -13,12 +13,14 @@ enum MenuFlag { struct PolledData { struct tm tm{}; - u32 battery_percetange{}; - PsmChargerType charger_type{}; NifmInternetConnectionType type{}; NifmInternetConnectionStatus status{}; u32 strength{}; u32 ip{}; + s64 sd_free{1}; + s64 sd_total{1}; + s64 emmc_free{1}; + s64 emmc_total{1}; }; struct MenuBase : Widget { diff --git a/sphaira/include/utils/utils.hpp b/sphaira/include/utils/utils.hpp index c4deb96..1dc6725 100644 --- a/sphaira/include/utils/utils.hpp +++ b/sphaira/include/utils/utils.hpp @@ -22,4 +22,11 @@ constexpr inline T AlignDown(T value, T align) { return value &~ (align - 1); } +// formats size to 1.23 MB in 1024 base. +// only uses 32 bytes so its SSO optimised, not need to cache. +std::string formatSizeStorage(u64 size); + +// formats size to 1.23 MB in 1000 base (used for progress bars). +std::string formatSizeNetwork(u64 size); + } // namespace sphaira::utils diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index 13a886c..eb5df01 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -1462,6 +1462,20 @@ void App::SetBackgroundMusicPause(bool pause) { } } +Result App::GetSdSize(s64* free, s64* total) { + fs::FsNativeContentStorage fs{FsContentStorageId_SdCard}; + R_TRY(fs.GetFreeSpace("/", free)); + R_TRY(fs.GetTotalSpace("/", total)); + R_SUCCEED(); +} + +Result App::GetEmmcSize(s64* free, s64* total) { + fs::FsNativeContentStorage fs{FsContentStorageId_User}; + R_TRY(fs.GetFreeSpace("/", free)); + R_TRY(fs.GetTotalSpace("/", total)); + R_SUCCEED(); +} + App::App(const char* argv0) { // boost mode is enabled in userAppInit(). ON_SCOPE_EXIT(App::SetBoostMode(false)); diff --git a/sphaira/source/dumper.cpp b/sphaira/source/dumper.cpp index 2571804..dfff8b8 100644 --- a/sphaira/source/dumper.cpp +++ b/sphaira/source/dumper.cpp @@ -336,7 +336,7 @@ Result DumpToFile(ui::ProgressBox* pbox, fs::Fs* fs, const fs::FsPath& root, Bas { fs::File file; - R_TRY(fs->OpenFile(temp_path, FsOpenMode_Write, &file)); + R_TRY(fs->OpenFile(temp_path, FsOpenMode_Write|FsOpenMode_Append, &file)); auto write_source = std::make_unique(&file); if (custom_transfer) { diff --git a/sphaira/source/main.cpp b/sphaira/source/main.cpp index d5dfd5e..1b42075 100644 --- a/sphaira/source/main.cpp +++ b/sphaira/source/main.cpp @@ -56,8 +56,6 @@ void userAppInit(void) { diagAbortWithResult(rc); if (R_FAILED(rc = plInitialize(PlServiceType_User))) diagAbortWithResult(rc); - if (R_FAILED(rc = psmInitialize())) - diagAbortWithResult(rc); if (R_FAILED(rc = nifmInitialize(NifmServiceType_User))) diagAbortWithResult(rc); if (R_FAILED(rc = accountInitialize(is_application ? AccountServiceType_Application : AccountServiceType_System))) @@ -83,7 +81,6 @@ void userAppExit(void) { setExit(); accountExit(); nifmExit(); - psmExit(); plExit(); socketExit(); // NOTE (DMC): prevents exfat corruption. diff --git a/sphaira/source/ui/menus/appstore.cpp b/sphaira/source/ui/menus/appstore.cpp index a511997..d41a16a 100644 --- a/sphaira/source/ui/menus/appstore.cpp +++ b/sphaira/source/ui/menus/appstore.cpp @@ -20,6 +20,8 @@ #include "web.hpp" #include "minizip_helper.hpp" +#include "utils/utils.hpp" + #include #include #include @@ -738,7 +740,7 @@ void EntryMenu::Draw(NVGcontext* vg, Theme* theme) { text_start_y += text_inc_y; gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "category: %s"_i18n.c_str(), m_entry.category.c_str()); text_start_y += text_inc_y; - gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "extracted: %.2f MiB"_i18n.c_str(), (double)m_entry.extracted / 1024.0); + gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "extracted: %s"_i18n.c_str(), utils::formatSizeStorage(m_entry.extracted).c_str()); text_start_y += text_inc_y; gfx::drawTextArgs(vg, text_start_x, text_start_y, font_size, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "app_dls: %s"_i18n.c_str(), AppDlToStr(m_entry.app_dls).c_str()); text_start_y += text_inc_y; diff --git a/sphaira/source/ui/menus/filebrowser.cpp b/sphaira/source/ui/menus/filebrowser.cpp index 9d9d14d..65eb6ee 100644 --- a/sphaira/source/ui/menus/filebrowser.cpp +++ b/sphaira/source/ui/menus/filebrowser.cpp @@ -10,6 +10,7 @@ #include "ui/error_box.hpp" #include "ui/music_player.hpp" +#include "utils/utils.hpp" #include "utils/devoptab.hpp" #include "log.hpp" @@ -603,10 +604,10 @@ void FsView::Draw(NVGcontext* vg, Theme* theme) { } if (e.file_count != -1) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%zd files"_i18n.c_str(), e.file_count); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(ThemeEntryID_TEXT_INFO), "%zd files"_i18n.c_str(), e.file_count); } if (e.dir_count != -1) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(text_id), "%zd dirs"_i18n.c_str(), e.dir_count); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT_INFO), "%zd dirs"_i18n.c_str(), e.dir_count); } } else if (e.IsFile() && !m_fs_entry.IsNoStatFile() && (e.file_size != -1 || !e.time_stamp.is_valid)) { if (!e.time_stamp.is_valid && !e.done_stat) { @@ -622,14 +623,9 @@ void FsView::Draw(NVGcontext* vg, Theme* theme) { const auto t = (time_t)(e.time_stamp.modified); struct tm tm{}; localtime_r(&t, &tm); - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(text_id), "%02u/%02u/%u", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900); - if ((double)e.file_size / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f KiB", (double)e.file_size / 1024.0); - } else if ((double)e.file_size / 1024.0 / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f MiB", (double)e.file_size / 1024.0 / 1024.0); - } else { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f GiB", (double)e.file_size / 1024.0 / 1024.0 / 1024.0); - } + + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT_INFO), "%02u/%02u/%u", tm.tm_mday, tm.tm_mon + 1, tm.tm_year + 1900); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(ThemeEntryID_TEXT_INFO), "%s", utils::formatSizeStorage(e.file_size).c_str()); } }); } diff --git a/sphaira/source/ui/menus/game_meta_menu.cpp b/sphaira/source/ui/menus/game_meta_menu.cpp index 6fae251..fa7b1be 100644 --- a/sphaira/source/ui/menus/game_meta_menu.cpp +++ b/sphaira/source/ui/menus/game_meta_menu.cpp @@ -10,6 +10,8 @@ #include "yati/nx/ncm.hpp" #include "yati/nx/es.hpp" +#include "utils/utils.hpp" + #include "title_info.hpp" #include "app.hpp" #include "defines.hpp" @@ -231,14 +233,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) { GetNcmSizeOfMetaStatus(e); } - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(text_id), "%s", ncm::GetReadableStorageIdStr(e.status.storageID)); - if ((double)e.size / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f KiB", (double)e.size / 1024.0); - } else if ((double)e.size / 1024.0 / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f MiB", (double)e.size / 1024.0 / 1024.0); - } else { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(text_id), "%.2f GiB", (double)e.size / 1024.0 / 1024.0 / 1024.0); - } + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) + 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT_INFO), "%s", ncm::GetReadableStorageIdStr(e.status.storageID)); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f) - 3, 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(ThemeEntryID_TEXT_INFO), "%s", utils::formatSizeStorage(e.size).c_str()); if (e.selected) { gfx::drawText(vg, x + text_xoffset - 80 / 2, y + (h / 2.f) - (24.f / 2), 24.f, "\uE14B", nullptr, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT_SELECTED)); diff --git a/sphaira/source/ui/menus/game_nca_menu.cpp b/sphaira/source/ui/menus/game_nca_menu.cpp index d1e7663..c93439d 100644 --- a/sphaira/source/ui/menus/game_nca_menu.cpp +++ b/sphaira/source/ui/menus/game_nca_menu.cpp @@ -344,15 +344,8 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) { } gfx::drawTextArgs(vg, x + text_xoffset, y + (h / 2.f), 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%s", ncm::GetContentTypeStr(e.content_type)); - gfx::drawTextArgs(vg, x + text_xoffset + 185, y + (h / 2.f), 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%s", utils::hexIdToStr(e.content_id).str); - - if ((double)e.size / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%.2f KiB", (double)e.size / 1024.0); - } else if ((double)e.size / 1024.0 / 1024.0 / 1024.0 <= 0.009) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%.2f MiB", (double)e.size / 1024.0 / 1024.0); - } else { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%.2f GiB", (double)e.size / 1024.0 / 1024.0 / 1024.0); - } + gfx::drawTextArgs(vg, x + text_xoffset + 150, y + (h / 2.f), 20.f, NVG_ALIGN_LEFT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "%s", utils::hexIdToStr(e.content_id).str); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(ThemeEntryID_TEXT_INFO), "%s", utils::formatSizeStorage(e.size).c_str()); if (e.missing) { gfx::drawText(vg, x + text_xoffset - 80 / 2, y + (h / 2.f) - (24.f / 2), 24.f, "\uE140", nullptr, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_ERROR)); diff --git a/sphaira/source/ui/menus/ghdl.cpp b/sphaira/source/ui/menus/ghdl.cpp index 550ba53..7755696 100644 --- a/sphaira/source/ui/menus/ghdl.cpp +++ b/sphaira/source/ui/menus/ghdl.cpp @@ -233,7 +233,7 @@ void Menu::Draw(NVGcontext* vg, Theme* theme) { nvgRestore(vg); if (!e.tag.empty()) { - gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(text_id), "version: %s", e.tag.c_str()); + gfx::drawTextArgs(vg, x + w - text_xoffset, y + (h / 2.f), 16.f, NVG_ALIGN_RIGHT | NVG_ALIGN_MIDDLE, theme->GetColour(ThemeEntryID_TEXT_INFO), "version: %s", e.tag.c_str()); } }); } diff --git a/sphaira/source/ui/menus/grid_menu_base.cpp b/sphaira/source/ui/menus/grid_menu_base.cpp index c890375..cb338d1 100644 --- a/sphaira/source/ui/menus/grid_menu_base.cpp +++ b/sphaira/source/ui/menus/grid_menu_base.cpp @@ -18,8 +18,9 @@ Vec4 Menu::DrawEntry(NVGcontext* vg, Theme* theme, bool draw_image, int layout, const auto& [x, y, w, h] = v; auto text_id = ThemeEntryID_TEXT; + auto info_id = ThemeEntryID_TEXT_INFO; if (selected) { - text_id = ThemeEntryID_TEXT_SELECTED; + text_id = info_id = ThemeEntryID_TEXT_SELECTED; gfx::drawRectOutline(vg, theme, 4.f, v); } else { DrawElement(v, ThemeEntryID_GRID); @@ -38,8 +39,8 @@ Vec4 Menu::DrawEntry(NVGcontext* vg, Theme* theme, bool draw_image, int layout, const auto text_clip_w = w - 30.f - text_off; const float font_size = 18; m_scroll_name.Draw(vg, selected, text_x, y + 45, text_clip_w, font_size, NVG_ALIGN_LEFT, theme->GetColour(text_id), name); - m_scroll_author.Draw(vg, selected, text_x, y + 80, text_clip_w, font_size, NVG_ALIGN_LEFT, theme->GetColour(text_id), author); - m_scroll_version.Draw(vg, selected, text_x, y + 115, text_clip_w, font_size, NVG_ALIGN_LEFT, theme->GetColour(text_id), version); + m_scroll_author.Draw(vg, selected, text_x, y + 80, text_clip_w, font_size, NVG_ALIGN_LEFT, theme->GetColour(info_id), author); + m_scroll_version.Draw(vg, selected, text_x, y + 115, text_clip_w, font_size, NVG_ALIGN_LEFT, theme->GetColour(info_id), version); } else { if (selected) { gfx::drawAppLable(vg, theme, m_scroll_name, x, y, w, name); diff --git a/sphaira/source/ui/menus/menu_base.cpp b/sphaira/source/ui/menus/menu_base.cpp index ace4d8c..bc53348 100644 --- a/sphaira/source/ui/menus/menu_base.cpp +++ b/sphaira/source/ui/menus/menu_base.cpp @@ -20,20 +20,24 @@ auto MenuBase::GetPolledData(bool force_refresh) -> PolledData { // doesn't have focus. if (force_refresh || timestamp.GetSeconds() >= 1) { data.tm = {}; - data.battery_percetange = {}; - data.charger_type = {}; data.type = {}; data.status = {}; data.strength = {}; data.ip = {}; + // avoid divide by zero if getting the size fails, for whatever reason. + data.sd_free = 1; + data.sd_total = 1; + data.emmc_free = 1; + data.emmc_total = 1; const auto t = std::time(NULL); localtime_r(&t, &data.tm); - psmGetBatteryChargePercentage(&data.battery_percetange); - psmGetChargerType(&data.charger_type); nifmGetInternetConnectionStatus(&data.type, &data.strength, &data.status); nifmGetCurrentIpAddress(&data.ip); + App::GetSdSize(&data.sd_free, &data.sd_total); + App::GetEmmcSize(&data.emmc_free, &data.emmc_total); + timestamp.Update(); } @@ -60,7 +64,7 @@ void MenuBase::Draw(NVGcontext* vg, Theme* theme) { const auto pdata = GetPolledData(); const float start_y = 70; - const float font_size = 22; + const float font_size = 20; const float spacing = 30; float start_x = 1220; @@ -77,21 +81,59 @@ void MenuBase::Draw(NVGcontext* vg, Theme* theme) { start_x -= spacing + (bounds[2] - bounds[0]); \ } - draw(ThemeEntryID_TEXT, 90, "%u\uFE6A", pdata.battery_percetange); + #define STORAGE_BAR_W 180 + #define STORAGE_BAR_H 8 - if (App::Get12HourTimeEnable()) { - draw(ThemeEntryID_TEXT, 132, "%02u:%02u %s", (pdata.tm.tm_hour == 0 || pdata.tm.tm_hour == 12) ? 12 : pdata.tm.tm_hour % 12, pdata.tm.tm_min, (pdata.tm.tm_hour < 12) ? "AM" : "PM"); - } else { - draw(ThemeEntryID_TEXT, 90, "%02u:%02u", pdata.tm.tm_hour, pdata.tm.tm_min); - } + const auto rounding = 2; + const auto storage_font = 19; + const auto storage_y = start_y - 30; + auto storage_x = start_x - STORAGE_BAR_W; - if (pdata.ip) { - draw(ThemeEntryID_TEXT, 0, "%u.%u.%u.%u", pdata.ip&0xFF, (pdata.ip>>8)&0xFF, (pdata.ip>>16)&0xFF, (pdata.ip>>24)&0xFF); - } else { - draw(ThemeEntryID_TEXT, 0, ("No Internet"_i18n).c_str()); - } + gfx::drawTextArgs(vg, storage_x, storage_y, storage_font, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "System %.1f GB"_i18n.c_str(), pdata.emmc_free / 1024.0 / 1024.0 / 1024.0); + // gfx::drawTextArgs(vg, storage_x, storage_y, storage_font, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "eMMC %.1f GB"_i18n.c_str(), pdata.emmc_free / 1024.0 / 1024.0 / 1024.0); + #if 0 + Vec4 prog_bar{storage_x, storage_y + 24, STORAGE_BAR_W, STORAGE_BAR_H}; + gfx::drawRect(vg, prog_bar, theme->GetColour(ThemeEntryID_PROGRESSBAR_BACKGROUND), rounding); + gfx::drawRect(vg, prog_bar.x, prog_bar.y, ((double)pdata.emmc_free / (double)pdata.emmc_total) * prog_bar.w, prog_bar.h, theme->GetColour(ThemeEntryID_PROGRESSBAR), rounding); + #else + gfx::drawRect(vg, storage_x, storage_y + 24, STORAGE_BAR_W, STORAGE_BAR_H, theme->GetColour(ThemeEntryID_TEXT_INFO), rounding); + gfx::drawRect(vg, storage_x + 1, storage_y + 24 + 1, STORAGE_BAR_W - 2, STORAGE_BAR_H - 2, theme->GetColour(ThemeEntryID_BACKGROUND), rounding); + gfx::drawRect(vg, storage_x + 2, storage_y + 24 + 2, STORAGE_BAR_W - (((double)pdata.emmc_free / (double)pdata.emmc_total) * STORAGE_BAR_W) - 4, STORAGE_BAR_H - 4, theme->GetColour(ThemeEntryID_TEXT_INFO), rounding); + #endif + + storage_x -= (STORAGE_BAR_W + spacing); + gfx::drawTextArgs(vg, storage_x, storage_y, storage_font, NVG_ALIGN_LEFT | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "microSD %.1f GB"_i18n.c_str(), pdata.sd_free / 1024.0 / 1024.0 / 1024.0); + gfx::drawRect(vg, storage_x, storage_y + 24, STORAGE_BAR_W, STORAGE_BAR_H, theme->GetColour(ThemeEntryID_TEXT_INFO), rounding); + gfx::drawRect(vg, storage_x + 1, storage_y + 24 + 1, STORAGE_BAR_W - 2, STORAGE_BAR_H - 2, theme->GetColour(ThemeEntryID_BACKGROUND), rounding); + gfx::drawRect(vg, storage_x + 2, storage_y + 24 + 2, STORAGE_BAR_W - (((double)pdata.sd_free / (double)pdata.sd_total) * STORAGE_BAR_W) - 4, STORAGE_BAR_H - 4, theme->GetColour(ThemeEntryID_TEXT_INFO), rounding); + start_x -= (STORAGE_BAR_W + spacing) * 2; + + // ran out of space, its one or the other. if (!App::IsApplication()) { draw(ThemeEntryID_ERROR, 0, ("[Applet Mode]"_i18n).c_str()); + } else { + if (pdata.ip) { + char ip_buf[32]; + std::snprintf(ip_buf, sizeof(ip_buf), "%u.%u.%u.%u", pdata.ip & 0xFF, (pdata.ip >> 8) & 0xFF, (pdata.ip >> 16) & 0xFF, (pdata.ip >> 24) & 0xFF); + gfx::textBounds(vg, 0, 0, bounds, ip_buf); + + char type_buf[32]; + if (pdata.type == NifmInternetConnectionType_WiFi) { + std::snprintf(type_buf, sizeof(type_buf), "Wi-Fi %.0f%%"_i18n.c_str(), ((float)pdata.strength / 3.F) * 100); + } else if (pdata.type == NifmInternetConnectionType_Ethernet) { + std::snprintf(type_buf, sizeof(type_buf), "Ethernet"_i18n.c_str()); + } else { + std::snprintf(type_buf, sizeof(type_buf), "Unknown"_i18n.c_str()); + } + + const auto ip_x = start_x; + const auto ip_w = bounds[2] - bounds[0]; + const auto type_x = ip_x - ip_w / 2; + gfx::drawTextArgs(vg, type_x, start_y - 25, storage_font - 1, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM, theme->GetColour(ThemeEntryID_TEXT_INFO), "%s", type_buf); + gfx::drawTextArgs(vg, ip_x, start_y, storage_font, NVG_ALIGN_RIGHT | NVG_ALIGN_BOTTOM, theme->GetColour(ThemeEntryID_TEXT), "%s", ip_buf); + } else { + draw(ThemeEntryID_TEXT, 0, ("No Internet"_i18n).c_str()); + } } #undef draw diff --git a/sphaira/source/ui/progress_box.cpp b/sphaira/source/ui/progress_box.cpp index 342684c..265e968 100644 --- a/sphaira/source/ui/progress_box.cpp +++ b/sphaira/source/ui/progress_box.cpp @@ -7,6 +7,7 @@ #include "threaded_file_transfer.hpp" #include "i18n.hpp" +#include "utils/utils.hpp" #include "utils/thread.hpp" #include @@ -152,16 +153,6 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void { const auto rad = 15; gfx::drawSpinner(vg, theme, prog_bar.x - pad - rad, prog_bar.y + prog_bar.h / 2, rad, armTicksToNs(armGetSystemTick()) / 1e+9); - const double speed_mb = (double)speed / (1024.0 * 1024.0); - const double speed_kb = (double)speed / (1024.0); - - char speed_str[32]; - if (speed_mb >= 0.01) { - std::snprintf(speed_str, sizeof(speed_str), "%.2f MiB/s", speed_mb); - } else { - std::snprintf(speed_str, sizeof(speed_str), "%.2f KiB/s", speed_kb); - } - const auto left = size - last_offset; const auto left_seconds = left / speed; const auto hours = left_seconds / (60 * 60); @@ -177,7 +168,7 @@ auto ProgressBox::Draw(NVGcontext* vg, Theme* theme) -> void { std::snprintf(time_str, sizeof(time_str), "%zu seconds remaining"_i18n.c_str(), seconds); } - gfx::drawTextArgs(vg, center_x, prog_bar.y + prog_bar.h + 30, 18, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "%s (%s)", time_str, speed_str); + gfx::drawTextArgs(vg, center_x, prog_bar.y + prog_bar.h + 30, 18, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), "%s (%s)", time_str, utils::formatSizeNetwork(speed).c_str()); } gfx::drawTextArgs(vg, center_x, m_pos.y + 40, 24, NVG_ALIGN_CENTER | NVG_ALIGN_TOP, theme->GetColour(ThemeEntryID_TEXT), action.c_str()); diff --git a/sphaira/source/utils/utils.cpp b/sphaira/source/utils/utils.cpp index 4c7e884..42a1a75 100644 --- a/sphaira/source/utils/utils.cpp +++ b/sphaira/source/utils/utils.cpp @@ -14,6 +14,25 @@ HashStr hexIdToStrInternal(auto id) { return str; } +std::string formatSizeInetrnal(double size, double base) { + static const char* const suffixes[] = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; + size_t suffix_index = 0; + + while (size >= base && suffix_index < std::size(suffixes) - 1) { + size /= base; + suffix_index++; + } + + char buffer[32]; + if (suffix_index == 0) { + std::snprintf(buffer, sizeof(buffer), "%.0f %s", size, suffixes[suffix_index]); + } else { + std::snprintf(buffer, sizeof(buffer), "%.2f %s", size, suffixes[suffix_index]); + } + + return buffer; +} + } // namespace HashStr hexIdToStr(FsRightsId id) { @@ -28,4 +47,12 @@ HashStr hexIdToStr(NcmContentId id) { return hexIdToStrInternal(id); } +std::string formatSizeStorage(u64 size) { + return formatSizeInetrnal(size, 1024.0); +} + +std::string formatSizeNetwork(u64 size) { + return formatSizeInetrnal(size, 1000.0); +} + } // namespace sphaira::utils diff --git a/sphaira/source/yati/nx/ncm.cpp b/sphaira/source/yati/nx/ncm.cpp index ca5b8b7..846522e 100644 --- a/sphaira/source/yati/nx/ncm.cpp +++ b/sphaira/source/yati/nx/ncm.cpp @@ -34,9 +34,9 @@ auto GetContentTypeStr(u8 content_type) -> const char* { case NcmContentType_Program: return "Program"; case NcmContentType_Data: return "Data"; case NcmContentType_Control: return "Control"; - case NcmContentType_HtmlDocument: return "HtmlDocument"; - case NcmContentType_LegalInformation: return "LegalInformation"; - case NcmContentType_DeltaFragment: return "DeltaFragment"; + case NcmContentType_HtmlDocument: return "Html"; + case NcmContentType_LegalInformation: return "Legal"; + case NcmContentType_DeltaFragment: return "Delta"; } return "Unknown";