From 49d7ec8ab81fb5bc38e5371495c992e564e69835 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Sun, 13 Jun 2021 15:32:37 -0400 Subject: [PATCH] GameCardTab: add ListItem elements. --- include/core/gamecard.h | 3 ++ include/defines.h | 5 ++- include/gamecard_tab.hpp | 7 ++++- romfs/i18n/en-US/gamecard_tab.json | 41 ++++++++++++++++++++++++ source/core/gamecard.c | 19 ++++++++++-- source/gamecard_tab.cpp | 50 ++++++++++++++++++++---------- 6 files changed, 104 insertions(+), 21 deletions(-) create mode 100644 romfs/i18n/en-US/gamecard_tab.json diff --git a/include/core/gamecard.h b/include/core/gamecard.h index 5f7f155..ee107a3 100644 --- a/include/core/gamecard.h +++ b/include/core/gamecard.h @@ -239,6 +239,9 @@ bool gamecardGetKeyArea(GameCardKeyArea *out); /// This area can also be read using gamecardReadStorage(), starting at offset 0. bool gamecardGetHeader(GameCardHeader *out); +/// Fills the provided GameCardInfo pointer. +bool gamecardGetDecryptedCardInfoArea(GameCardInfo *out); + /// Fills the provided FsGameCardCertificate pointer. /// This area can also be read using gamecardReadStorage(), starting at GAMECARD_CERTIFICATE_OFFSET. bool gamecardGetCertificate(FsGameCardCertificate *out); diff --git a/include/defines.h b/include/defines.h index def0f41..338b570 100644 --- a/include/defines.h +++ b/include/defines.h @@ -64,9 +64,12 @@ #define FAT32_FILESIZE_LIMIT (u64)0xFFFFFFFF /* 4 GiB - 1 (4294967295 bytes). */ -/* Path defines. */ +/* Other defines. */ #define APP_BASE_PATH "sdmc:/switch/" APP_TITLE "/" #define BIS_SYSTEM_PARTITION_MOUNT_NAME "sys:" +#define GITHUB_REPOSITORY_URL "https://github.com/DarkMatterCore/nxdumptool" +#define GITHUB_NEW_ISSUE_URL GITHUB_REPOSITORY_URL "/issues/new/choose" + #endif /* __DEFINES_H__ */ diff --git a/include/gamecard_tab.hpp b/include/gamecard_tab.hpp index 5518288..4b48f04 100644 --- a/include/gamecard_tab.hpp +++ b/include/gamecard_tab.hpp @@ -39,7 +39,12 @@ namespace nxdt::views ErrorFrame *error_frame = nullptr; brls::List *list = nullptr; - brls::ListItem *placeholder = nullptr; + brls::ListItem *dump_card_image = nullptr; + brls::ListItem *dump_certificate = nullptr; + brls::ListItem *dump_header = nullptr; + brls::ListItem *dump_decrypted_cardinfo = nullptr; + brls::ListItem *dump_initial_data = nullptr; + brls::ListItem *dump_hfs_partitions = nullptr; std::vector views; int view_index = -1; diff --git a/romfs/i18n/en-US/gamecard_tab.json b/romfs/i18n/en-US/gamecard_tab.json new file mode 100644 index 0000000..71d8e64 --- /dev/null +++ b/romfs/i18n/en-US/gamecard_tab.json @@ -0,0 +1,41 @@ +{ + "error_frame": { + "not_inserted": "No gamecard inserted.", + "processing": "Processing gamecard, please wait...", + "nogc_enabled": "A gamecard has been inserted, but the \"nogc\" patch is enabled.\nNothing at all can be done with the inserted gamecard.\nDisabling this patch *will* update the Lotus ASIC firmware if it's outdated.\nConsider disabling this patch if you wish to use gamecard dumping features.", + "lafw_update_required": "A gamecard has been inserted, but a Lotus ASIC firmware update is required.\nUpdate your console using the inserted gamecard and try again.", + "info_not_loaded": "A gamecard has been inserted, but an unexpected I/O error occurred.\nPlease report this issue at \"{0}\"." + }, + + "list": { + "dump_card_image": { + "label": "Dump gamecard image", + "description": "Generates a raw gamecard image. This is the option most people will want to use." + }, + + "dump_certificate": { + "label": "Dump gamecard certificate", + "description": "The gamecard certificate is used to unequivocally identify each individual gamecard." + }, + + "dump_header": { + "label": "Dump gamecard header", + "description": "The gamecard header holds information such as the location of the root HFS partition and the gamecard capacity.\nOnly useful for developers, preservationists and advanced users." + }, + + "dump_decrypted_cardinfo": { + "label": "Dump decrypted CardInfo area", + "description": "The CardInfo area holds information such as the bundled system update version and the Lotus ASIC firmware version required by the gamecard.\nThis area is part of the gamecard header, but it's always encrypted.\nOnly useful for developers, preservationists and advanced users." + }, + + "dump_initial_data": { + "label": "Dump InitialData area", + "description": "The InitialData area holds cryptographic information used by the Lotus ASIC to communicate with the gamecard.\nIt can't be dumped through normal means - it's not part of the storage areas from gamecard images.\nOnly useful for developers, preservationists and advanced users." + }, + + "dump_hfs_partitions": { + "label": "Dump Hash File System (HFS) partitions", + "description": "Dumps data from the HFS partitions within the gamecard storage areas, in both raw and extracted forms." + } + } +} diff --git a/source/core/gamecard.c b/source/core/gamecard.c index 885070c..b614318 100644 --- a/source/core/gamecard.c +++ b/source/core/gamecard.c @@ -164,7 +164,7 @@ static void gamecardFreeInfo(bool clear_status); static bool gamecardReadHeader(void); -static bool gamecardGetDecryptedCardInfoArea(void); +static bool _gamecardGetDecryptedCardInfoArea(void); static bool gamecardReadInitialData(GameCardKeyArea *out); @@ -346,6 +346,19 @@ bool gamecardGetHeader(GameCardHeader *out) return ret; } +bool gamecardGetDecryptedCardInfoArea(GameCardInfo *out) +{ + bool ret = false; + + SCOPED_LOCK(&g_gameCardMutex) + { + ret = (g_gameCardInterfaceInit && g_gameCardStatus == GameCardStatus_InsertedAndInfoLoaded && out); + if (ret) memcpy(out, &g_gameCardInfoArea, sizeof(GameCardInfo)); + } + + return ret; +} + bool gamecardGetCertificate(FsGameCardCertificate *out) { bool ret = false; @@ -667,7 +680,7 @@ static void gamecardLoadInfo(void) if (!gamecardReadHeader()) goto end; /* Get decrypted CardInfo area from header. */ - if (!gamecardGetDecryptedCardInfoArea()) goto end; + if (!_gamecardGetDecryptedCardInfoArea()) goto end; /* Check if we meet the Lotus ASIC firmware (LAFW) version requirement. */ /* Lotus treats the GameCardFwVersion field as the maximum unsupported LAFW version, instead of treating it as the minimum supported version. */ @@ -820,7 +833,7 @@ static bool gamecardReadHeader(void) return true; } -static bool gamecardGetDecryptedCardInfoArea(void) +static bool _gamecardGetDecryptedCardInfoArea(void) { const u8 *card_info_key = NULL; u8 card_info_iv[AES_128_KEY_SIZE] = {0}; diff --git a/source/gamecard_tab.cpp b/source/gamecard_tab.cpp index 1b29e3e..1f769be 100644 --- a/source/gamecard_tab.cpp +++ b/source/gamecard_tab.cpp @@ -22,20 +22,38 @@ #include #include -using namespace brls::i18n::literals; /* For _i18n. */ +namespace i18n = brls::i18n; /* For getStr(). */ +using namespace i18n::literals; /* For _i18n. */ namespace nxdt::views { GameCardTab::GameCardTab(nxdt::tasks::GameCardTask *gc_status_task) : brls::LayerView(), gc_status_task(gc_status_task) { /* Add error frame. */ - this->error_frame = new ErrorFrame("No gamecard inserted."); + this->error_frame = new ErrorFrame("gamecard_tab/error_frame/not_inserted"_i18n); this->addLayerWrapper(this->error_frame); /* Add list. */ this->list = new brls::List(); - this->placeholder = new brls::ListItem("Placeholder"); - this->list->addView(this->placeholder); + + this->dump_card_image = new brls::ListItem("gamecard_tab/list/dump_card_image/label"_i18n, "gamecard_tab/list/dump_card_image/description"_i18n); + this->list->addView(this->dump_card_image); + + this->dump_certificate = new brls::ListItem("gamecard_tab/list/dump_certificate/label"_i18n, "gamecard_tab/list/dump_certificate/description"_i18n); + this->list->addView(this->dump_certificate); + + this->dump_header = new brls::ListItem("gamecard_tab/list/dump_header/label"_i18n, "gamecard_tab/list/dump_header/description"_i18n); + this->list->addView(this->dump_header); + + this->dump_decrypted_cardinfo = new brls::ListItem("gamecard_tab/list/dump_decrypted_cardinfo/label"_i18n, "gamecard_tab/list/dump_decrypted_cardinfo/description"_i18n); + this->list->addView(this->dump_decrypted_cardinfo); + + this->dump_initial_data = new brls::ListItem("gamecard_tab/list/dump_initial_data/label"_i18n, "gamecard_tab/list/dump_initial_data/description"_i18n); + this->list->addView(this->dump_initial_data); + + this->dump_hfs_partitions = new brls::ListItem("gamecard_tab/list/dump_hfs_partitions/label"_i18n, "gamecard_tab/list/dump_hfs_partitions/description"_i18n); + this->list->addView(this->dump_hfs_partitions); + this->addLayerWrapper(this->list); /* Setup gamecard status task. */ @@ -45,24 +63,19 @@ namespace nxdt::views switch(gc_status) { case GameCardStatus_NotInserted: - this->error_frame->SetMessage("No gamecard inserted."); + this->error_frame->SetMessage("gamecard_tab/error_frame/not_inserted"_i18n); break; case GameCardStatus_Processing: - this->error_frame->SetMessage("Processing gamecard, please wait..."); + this->error_frame->SetMessage("gamecard_tab/error_frame/processing"_i18n); break; case GameCardStatus_NoGameCardPatchEnabled: - this->error_frame->SetMessage("A gamecard has been inserted, but the \"nogc\" patch is enabled.\n" \ - "Nothing at all can be done with the inserted gamecard.\n" \ - "Disabling this patch *will* update the Lotus ASIC firmware if it's outdated.\n" \ - "Consider disabling this patch if you wish to use gamecard dumping features."); + this->error_frame->SetMessage("gamecard_tab/error_frame/nogc_enabled"_i18n); break; case GameCardStatus_LotusAsicFirmwareUpdateRequired: - this->error_frame->SetMessage("A gamecard has been inserted, but a Lotus ASIC firmware update is required.\n" \ - "Update your console using the inserted gamecard and try again."); + this->error_frame->SetMessage("gamecard_tab/error_frame/lafw_update_required"_i18n); break; case GameCardStatus_InsertedAndInfoNotLoaded: - this->error_frame->SetMessage("A gamecard has been inserted, but an unexpected I/O error occurred.\n" \ - "Please check the logfile and report this issue to " APP_AUTHOR "."); + this->error_frame->SetMessage(i18n::getStr("gamecard_tab/error_frame/info_not_loaded"_i18n, GITHUB_NEW_ISSUE_URL)); break; case GameCardStatus_InsertedAndInfoLoaded: this->changeLayerWrapper(this->list); @@ -94,6 +107,7 @@ namespace nxdt::views void GameCardTab::changeLayerWrapper(brls::View* view) { int index = -1; + brls::View *current_focus = brls::Application::getCurrentFocus(); for(size_t i = 0; i < this->views.size(); i++) { @@ -106,8 +120,12 @@ namespace nxdt::views if (index == -1) return; - /* TODO: check all ListItem elements using a loop. */ - if (brls::Application::getCurrentFocus() == this->placeholder) brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false); + /* Focus the sidebar if we're currently focusing a ListItem element. */ + if (current_focus && (current_focus == this->dump_card_image || current_focus == this->dump_certificate || current_focus == this->dump_header || \ + current_focus == this->dump_decrypted_cardinfo || current_focus == this->dump_initial_data || current_focus == this->dump_hfs_partitions)) + { + brls::Application::onGamepadButtonPressed(GLFW_GAMEPAD_BUTTON_DPAD_LEFT, false); + } this->changeLayer(index); this->invalidate(true);