diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 7d6f6e5..1eab01f 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -173,7 +173,7 @@ typedef struct { u8 rom_size; ///< GameCardRomSize. u8 header_version; ///< Always 0. u8 flags; ///< GameCardFlags. - u64 package_id; ///< Used for challenge–response authentication. + u64 package_id; ///< Used for challenge-response authentication. u32 valid_data_end_address; ///< Expressed in GAMECARD_PAGE_SIZE units. u8 reserved[0x4]; u8 card_info_iv[AES_128_KEY_SIZE]; ///< AES-128-CBC IV for the CardInfo area (reversed). @@ -183,7 +183,7 @@ typedef struct { u8 initial_data_hash[SHA256_HASH_SIZE]; u32 sel_sec; ///< GameCardSelSec. u32 sel_t1_key; ///< Always 2. - u32 sel_key; ///> Always 0. + u32 sel_key; ///< Always 0. u32 lim_area; ///< Expressed in GAMECARD_PAGE_SIZE units. GameCardInfo card_info; } GameCardHeader; diff --git a/include/core/nca.h b/include/core/nca.h index 4c95af3..65e5129 100644 --- a/include/core/nca.h +++ b/include/core/nca.h @@ -71,19 +71,20 @@ typedef enum { /// 'NcaKeyGeneration_Current' will always point to the last known key generation value. typedef enum { - NcaKeyGeneration_Since100NUP = 0, ///< 1.0.0 - 2.3.0. - NcaKeyGeneration_Since300NUP = 2, ///< 3.0.0. - NcaKeyGeneration_Since301NUP = 3, ///< 3.0.1 - 3.0.2. - NcaKeyGeneration_Since400NUP = 4, ///< 4.0.0 - 4.1.0. - NcaKeyGeneration_Since500NUP = 5, ///< 5.0.0 - 5.1.0. - NcaKeyGeneration_Since600NUP = 6, ///< 6.0.0 - 6.1.0. - NcaKeyGeneration_Since620NUP = 7, ///< 6.2.0. - NcaKeyGeneration_Since700NUP = 8, ///< 7.0.0 - 8.0.1. - NcaKeyGeneration_Since810NUP = 9, ///< 8.1.0 - 8.1.1. - NcaKeyGeneration_Since900NUP = 10, ///< 9.0.0 - 9.0.1. - NcaKeyGeneration_Since910NUP = 11, ///< 9.1.0 - 12.0.2. - NcaKeyGeneration_Current = NcaKeyGeneration_Since910NUP, - NcaKeyGeneration_Max = 32 + NcaKeyGeneration_Since100NUP = 0, ///< 1.0.0 - 2.3.0. + NcaKeyGeneration_Since300NUP = 2, ///< 3.0.0. + NcaKeyGeneration_Since301NUP = 3, ///< 3.0.1 - 3.0.2. + NcaKeyGeneration_Since400NUP = 4, ///< 4.0.0 - 4.1.0. + NcaKeyGeneration_Since500NUP = 5, ///< 5.0.0 - 5.1.0. + NcaKeyGeneration_Since600NUP = 6, ///< 6.0.0 - 6.1.0. + NcaKeyGeneration_Since620NUP = 7, ///< 6.2.0. + NcaKeyGeneration_Since700NUP = 8, ///< 7.0.0 - 8.0.1. + NcaKeyGeneration_Since810NUP = 9, ///< 8.1.0 - 8.1.1. + NcaKeyGeneration_Since900NUP = 10, ///< 9.0.0 - 9.0.1. + NcaKeyGeneration_Since910NUP = 11, ///< 9.1.0 - 12.0.3. + NcaKeyGeneration_Since1210NUP = 12, ///< 12.1.0. + NcaKeyGeneration_Current = NcaKeyGeneration_Since1210NUP, + NcaKeyGeneration_Max = 32 } NcaKeyGeneration; typedef enum { @@ -96,7 +97,7 @@ typedef enum { /// 'NcaMainSignatureKeyGeneration_Current' will always point to the last known key generation value. typedef enum { NcaMainSignatureKeyGeneration_Since100NUP = 0, ///< 1.0.0 - 8.1.1. - NcaMainSignatureKeyGeneration_Since900NUP = 1, ///< 9.0.0 - 12.0.2. + NcaMainSignatureKeyGeneration_Since900NUP = 1, ///< 9.0.0 - 12.1.0. NcaMainSignatureKeyGeneration_Current = NcaMainSignatureKeyGeneration_Since900NUP, NcaMainSignatureKeyGeneration_Max = (NcaMainSignatureKeyGeneration_Current + 1) } NcaMainSignatureKeyGeneration; diff --git a/include/tasks.hpp b/include/tasks.hpp index 2e7e4fb..5ee186f 100644 --- a/include/tasks.hpp +++ b/include/tasks.hpp @@ -89,6 +89,7 @@ namespace nxdt::tasks GameCardStatusEvent gc_status_event; GameCardStatus cur_gc_status = GameCardStatus_NotInserted; GameCardStatus prev_gc_status = GameCardStatus_NotInserted; + bool first_notification = true; protected: void run(retro_time_t current_time) override; diff --git a/libs/borealis b/libs/borealis index 6a523eb..6d95c14 160000 --- a/libs/borealis +++ b/libs/borealis @@ -1 +1 @@ -Subproject commit 6a523eb2d31f1d8c484a8c090359c74e20b0a548 +Subproject commit 6d95c14f2f91dc6c2bcb1d1d0e4ebdd1f00f7c3b diff --git a/romfs/i18n/en-US/tasks.json b/romfs/i18n/en-US/tasks.json index ed91612..e72cd01 100644 --- a/romfs/i18n/en-US/tasks.json +++ b/romfs/i18n/en-US/tasks.json @@ -1,9 +1,10 @@ { "notifications": { - "gamecard": "Gamecard status change detected!", - "user_titles": "User titles updated!", - "ums_device": "USB Mass Storage devices updated!", - "usb_host_connected": "USB host connected!", - "usb_host_disconnected": "USB host disconnected!" + "gamecard_status_updated": "Gamecard status updated", + "gamecard_ejected": "Gamecard ejected", + "user_titles": "User titles updated", + "ums_device": "USB Mass Storage devices updated", + "usb_host_connected": "USB host connected", + "usb_host_disconnected": "USB host disconnected" } } diff --git a/source/about_tab.cpp b/source/about_tab.cpp index 2b5c69b..1e38964 100644 --- a/source/about_tab.cpp +++ b/source/about_tab.cpp @@ -87,7 +87,7 @@ namespace nxdt::views this->logo->getWidth(), this->logo->getHeight()); - this->logo->invalidate(true); + this->logo->invalidate(); brls::ScrollView::layout(vg, style, stash); } diff --git a/source/core/title.c b/source/core/title.c index 8683533..aba6ccc 100644 --- a/source/core/title.c +++ b/source/core/title.c @@ -24,10 +24,10 @@ #include "gamecard.h" #include "nacp.h" -#define NS_APPLICATION_RECORD_LIMIT 4096 +#define NS_APPLICATION_RECORD_BLOCK_SIZE 1024 -#define TITLE_STORAGE_COUNT 4 /* GameCard, BuiltInSystem, BuiltInUser, SdCard. */ -#define TITLE_STORAGE_INDEX(storage_id) ((storage_id) - NcmStorageId_GameCard) +#define TITLE_STORAGE_COUNT 4 /* GameCard, BuiltInSystem, BuiltInUser, SdCard. */ +#define TITLE_STORAGE_INDEX(storage_id) ((storage_id) - NcmStorageId_GameCard) /* Type definitions. */ @@ -464,7 +464,8 @@ static const TitleSystemEntry g_systemTitles[] = { { 0x100000000000021F, "nfc" }, { 0x1000000000000220, "psc" }, { 0x1000000000000221, "capsrv" }, - { 0x1000000000000222, "am" } + { 0x1000000000000222, "am" }, + { 0x1000000000000223, "ssl" } }; static const u32 g_systemTitlesCount = MAX_ELEMENTS(g_systemTitles); @@ -1459,26 +1460,41 @@ static bool titleGenerateMetadataEntriesFromNsRecords(void) { Result rc = 0; - NsApplicationRecord *app_records = NULL; - u32 app_records_count = 0, extra_app_count = 0; + NsApplicationRecord *app_records = NULL, *tmp_app_records = NULL; + u32 app_records_block_count = 0, app_records_count = 0, extra_app_count = 0; + size_t app_records_size = 0, app_records_block_size = (NS_APPLICATION_RECORD_BLOCK_SIZE * sizeof(NsApplicationRecord)); bool success = false, free_entries = false; - /* Allocate memory for the NS application records. */ - app_records = calloc(NS_APPLICATION_RECORD_LIMIT, sizeof(NsApplicationRecord)); - if (!app_records) - { - LOG_MSG("Failed to allocate memory for NS application records!"); - return false; - } - - /* Retrieve NS application records. */ - rc = nsListApplicationRecord(app_records, NS_APPLICATION_RECORD_LIMIT, 0, (s32*)&app_records_count); - if (R_FAILED(rc)) - { - LOG_MSG("nsListApplicationRecord failed! (0x%08X).", rc); - goto end; - } + /* Retrieve NS application records in a loop until we get them all. */ + do { + /* Allocate memory for the NS application records. */ + tmp_app_records = realloc(app_records, app_records_size + app_records_block_size); + if (!tmp_app_records) + { + LOG_MSG("Failed to reallocate NS application records buffer! (%u)", app_records_count); + goto end; + } + + app_records = tmp_app_records; + tmp_app_records = NULL; + app_records_size += app_records_block_size; + + /* Clear newly allocated block. */ + NsApplicationRecord *app_records_block = &(app_records[app_records_count]); + memset(app_records_block, 0, app_records_block_size); + + /* Retrieve NS application records. */ + rc = nsListApplicationRecord(app_records_block, NS_APPLICATION_RECORD_BLOCK_SIZE, (s32)app_records_count, (s32*)&app_records_block_count); + if (R_FAILED(rc)) + { + LOG_MSG("nsListApplicationRecord failed! (0x%08X) (%u).", rc, app_records_count); + if (!app_records_count) goto end; + break; /* Gotta work with what we have. */ + } + + app_records_count += app_records_block_count; + } while(app_records_block_count >= NS_APPLICATION_RECORD_BLOCK_SIZE); /* Return right away if no records were retrieved. */ if (!app_records_count) diff --git a/source/error_frame.cpp b/source/error_frame.cpp index 11b89eb..b36de3f 100644 --- a/source/error_frame.cpp +++ b/source/error_frame.cpp @@ -92,6 +92,6 @@ namespace nxdt::views void ErrorFrame::SetMessage(std::string msg) { this->label->setText(msg); - this->invalidate(true); + this->invalidate(); } } diff --git a/source/root_view.cpp b/source/root_view.cpp index 349bf78..f01b03f 100644 --- a/source/root_view.cpp +++ b/source/root_view.cpp @@ -50,33 +50,40 @@ namespace nxdt::views this->applet_mode_lbl->setParent(this); this->time_lbl = new brls::Label(brls::LabelStyle::SMALL, ""); + this->time_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT); this->time_lbl->setVerticalAlign(NVG_ALIGN_TOP); this->time_lbl->setParent(this); this->battery_icon = new brls::Label(brls::LabelStyle::SMALL, ""); this->battery_icon->setFont(material); + this->battery_icon->setHorizontalAlign(NVG_ALIGN_RIGHT); this->battery_icon->setVerticalAlign(NVG_ALIGN_TOP); this->battery_icon->setParent(this); this->battery_percentage = new brls::Label(brls::LabelStyle::SMALL, ""); + this->battery_percentage->setHorizontalAlign(NVG_ALIGN_RIGHT); this->battery_percentage->setVerticalAlign(NVG_ALIGN_TOP); this->battery_percentage->setParent(this); this->connection_icon = new brls::Label(brls::LabelStyle::SMALL, ""); this->connection_icon->setFont(material); + this->connection_icon->setHorizontalAlign(NVG_ALIGN_RIGHT); this->connection_icon->setVerticalAlign(NVG_ALIGN_TOP); this->connection_icon->setParent(this); this->connection_status_lbl = new brls::Label(brls::LabelStyle::SMALL, ""); + this->connection_status_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT); this->connection_status_lbl->setVerticalAlign(NVG_ALIGN_TOP); this->connection_status_lbl->setParent(this); this->usb_icon = new brls::Label(brls::LabelStyle::SMALL, "\uE1E0"); this->usb_icon->setFont(material); + this->usb_icon->setHorizontalAlign(NVG_ALIGN_RIGHT); this->usb_icon->setVerticalAlign(NVG_ALIGN_TOP); this->usb_icon->setParent(this); this->usb_host_speed_lbl = new brls::Label(brls::LabelStyle::SMALL, "root_view/not_connected"_i18n); + this->usb_host_speed_lbl->setHorizontalAlign(NVG_ALIGN_RIGHT); this->usb_host_speed_lbl->setVerticalAlign(NVG_ALIGN_TOP); this->usb_host_speed_lbl->setParent(this); @@ -151,18 +158,12 @@ namespace nxdt::views /* Update network labels. */ this->connection_icon->setText(!connection_type ? "\uE195" : (connection_type == NifmInternetConnectionType_WiFi ? "\uE63E" : "\uE8BE")); this->connection_status_lbl->setText(ip_addr ? std::string(ip_addr) : "root_view/not_connected"_i18n); - - /* Update layout. */ - this->invalidate(true); }); /* Subscribe to USB host event. */ this->usb_host_task_sub = this->usb_host_task->RegisterListener([this](UsbHostSpeed usb_host_speed) { /* Update USB host speed label. */ this->usb_host_speed_lbl->setText(usb_host_speed ? fmt::format("USB {}.0", usb_host_speed) : "root_view/not_connected"_i18n); - - /* Update layout. */ - this->invalidate(true); }); } @@ -222,36 +223,47 @@ namespace nxdt::views y_pos = (this->y + (style->AppletFrame.headerHeightRegular / 2) + style->AppletFrame.titleOffset); this->applet_mode_lbl->setBoundaries(x_pos, y_pos, 0, 0); + this->applet_mode_lbl->invalidate(); } /* Time label. */ - x_pos = (this->x + this->width - (style->AppletFrame.separatorSpacing * 2) - this->time_lbl->getTextWidth()); + x_pos = (this->x + this->width - style->AppletFrame.separatorSpacing - style->AppletFrame.footerTextSpacing); y_pos = this->y + style->AppletFrame.imageTopPadding; this->time_lbl->setBoundaries(x_pos, y_pos, 0, 0); + this->time_lbl->invalidate(); /* Battery stats and network connection labels. */ - x_pos = (this->x + this->width - (style->AppletFrame.separatorSpacing * 2) - this->connection_status_lbl->getTextWidth()); y_pos += (this->time_lbl->getTextHeight() + 5); this->connection_status_lbl->setBoundaries(x_pos, y_pos, 0, 0); - x_pos -= (5 + this->connection_icon->getTextWidth()); + this->connection_status_lbl->invalidate(); + + x_pos -= (5 + this->connection_status_lbl->getTextWidth()); this->connection_icon->setBoundaries(x_pos, y_pos, 0, 0); - x_pos -= (10 + this->battery_percentage->getTextWidth()); + this->connection_icon->invalidate(); + + x_pos -= (10 + this->connection_icon->getTextWidth()); this->battery_percentage->setBoundaries(x_pos, y_pos, 0, 0); - x_pos -= (5 + this->battery_icon->getTextWidth()); + this->battery_percentage->invalidate(); + + x_pos -= (5 + this->battery_percentage->getTextWidth()); this->battery_icon->setBoundaries(x_pos, y_pos, 0, 0); + this->battery_icon->invalidate(); /* USB host speed labels. */ - x_pos = (this->x + this->width - (style->AppletFrame.separatorSpacing * 2) - this->usb_host_speed_lbl->getTextWidth()); + x_pos = (this->x + this->width - style->AppletFrame.separatorSpacing - style->AppletFrame.footerTextSpacing); y_pos += (this->connection_status_lbl->getTextHeight() + 5); this->usb_host_speed_lbl->setBoundaries(x_pos, y_pos, 0, 0); - x_pos -= (5 + this->usb_icon->getTextWidth()); + this->usb_host_speed_lbl->invalidate(); + + x_pos -= (5 + this->usb_host_speed_lbl->getTextWidth()); this->usb_icon->setBoundaries(x_pos, y_pos, 0, 0); + this->usb_icon->invalidate(); } } diff --git a/source/tasks.cpp b/source/tasks.cpp index 32c3a3d..87268cc 100644 --- a/source/tasks.cpp +++ b/source/tasks.cpp @@ -86,6 +86,8 @@ namespace nxdt::tasks { brls::RepeatingTask::start(); brls::Logger::debug("Gamecard task started."); + + this->first_notification = (gamecardGetStatus() >= GameCardStatus_Processing); } GameCardTask::~GameCardTask(void) @@ -101,7 +103,24 @@ namespace nxdt::tasks if (this->cur_gc_status != this->prev_gc_status) { brls::Logger::debug("Gamecard status change triggered: {}.", this->cur_gc_status); - brls::Application::notify("tasks/notifications/gamecard"_i18n); + + if (!this->first_notification) + { + if (this->prev_gc_status == GameCardStatus_NotInserted && this->cur_gc_status == GameCardStatus_Processing) + { + brls::Application::notify("gamecard_tab/error_frame/processing"_i18n); + } else + if (this->prev_gc_status == GameCardStatus_Processing && this->cur_gc_status > GameCardStatus_Processing) + { + brls::Application::notify("tasks/notifications/gamecard_status_updated"_i18n); + } else + if (this->cur_gc_status == GameCardStatus_NotInserted) + { + brls::Application::notify("tasks/notifications/gamecard_ejected"_i18n); + } + } else { + this->first_notification = false; + } /* Update previous gamecard status. */ this->prev_gc_status = this->cur_gc_status; @@ -142,7 +161,7 @@ namespace nxdt::tasks if (titleIsGameCardInfoUpdated()) { brls::Logger::debug("Title info updated."); - brls::Application::notify("tasks/notifications/user_titles"_i18n); + //brls::Application::notify("tasks/notifications/user_titles"_i18n); /* Update user metadata vector. */ this->PopulateApplicationMetadataVector(false);