From a122605b6edbf925315901bcccf728f36cc820d5 Mon Sep 17 00:00:00 2001 From: Pablo Curiel Date: Thu, 21 Jun 2018 20:46:17 -0400 Subject: [PATCH] Update to v1.0.1. --- Makefile | 2 +- README.md | 16 +++++++++++++- source/dumper.c | 41 +++++++++++------------------------ source/main.c | 9 +++++--- source/ui.c | 57 +++++++++++++++++++++++++++++++++---------------- source/ui.h | 11 +++++++--- source/util.c | 22 +++++++++---------- source/util.h | 2 +- 8 files changed, 92 insertions(+), 68 deletions(-) diff --git a/Makefile b/Makefile index ab08fd2..5c84f4f 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ include $(DEVKITPRO)/libnx/switch_rules VERSION_MAJOR := 1 VERSION_MINOR := 0 -VERSION_MICRO := 0 +VERSION_MICRO := 1 APP_TITLE := Game Card Dump Tool APP_AUTHOR := MCMrARM, DarkMatterCore diff --git a/README.md b/README.md index cd88674..c25dd1f 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Nintendo Switch Game Card Dump Tool Main features -------------- -* Generates full XCI cartridge dumps (with optional certificate removal). All dumps are padded with 0xFF up to the actual game card size. +* Generates full XCI cartridge dumps (with optional certificate removal). All dumps are padded with 0xFF to match the full game card size. * Precise HFS0 raw partition dumping (using the root HFS0 header from the game card). * Partition filesystem data dumping. * Partition filesystem browser (with manual file dump support). @@ -21,3 +21,17 @@ Thanks to * Foen, for giving me some pretty good hints about how to use the NCM service. * Yellows8, for helping me fix a silly bug in my implementation of some NCM service IPC calls. * The folks from ReSwitched, for working towards the creation of a good homebrew ecosystem. + +Changelog +-------------- + +**v1.0.1:** + +* Minor UI fixes and tweaks. +* Added some missing Title ID checks in uiLoop(). +* All calls to uiStatusMsg() are now properly identified. +* Increased wait time to 2 seconds when a new gamecard is detected. + +**v1.0.0:** + +Initial release. diff --git a/source/dumper.c b/source/dumper.c index 21a5b54..01fd2e6 100644 --- a/source/dumper.c +++ b/source/dumper.c @@ -45,38 +45,33 @@ bool getRootHfs0Header(FsDeviceOperator* fsOperator) Result result; FsStorage gameCardStorage; - //breaks = 0; - //uiClearScreen(); - hfs0_partition_cnt = 0; workaroundPartitionZeroAccess(fsOperator); if (R_FAILED(result = fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "GetGameCardHandle failed! (0x%08X)", result); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: GetGameCardHandle failed! (0x%08X)", result); return false; } if (R_FAILED(result = fsOpenGameCardStorage(&gameCardStorage, handle, 0))) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "OpenGameCardStorage failed! (0x%08X)", result); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: OpenGameCardStorage failed! (0x%08X)", result); return false; } char *gamecard_header = (char*)malloc(GAMECARD_HEADER_SIZE); if (!gamecard_header) { + uiStatusMsg("getRootHfs0Header: Unable to allocate memory for the gamecard header!"); fsStorageClose(&gameCardStorage); return false; } if (R_FAILED(result = fsStorageRead(&gameCardStorage, 0, gamecard_header, GAMECARD_HEADER_SIZE))) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "StorageRead failed! (0x%08X)", result); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: StorageRead failed to read %u-byte chunk from offset 0x%016lX! (0x%08X)", GAMECARD_HEADER_SIZE, 0, result); free(gamecard_header); @@ -108,8 +103,7 @@ bool getRootHfs0Header(FsDeviceOperator* fsOperator) gameCardSize = GAMECARD_SIZE_32GiB; break; default: - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Invalid game card size value: 0x%02X", cardSize); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: Invalid game card size value: 0x%02X", cardSize); free(gamecard_header); @@ -125,19 +119,16 @@ bool getRootHfs0Header(FsDeviceOperator* fsOperator) free(gamecard_header); - /*snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Root HFS0 offset: 0x%016lX", hfs0_offset); - uiDrawString(strbuf, 0, breaks * 8, 255, 255, 255); - breaks++; + /*uiStatusMsg("getRootHfs0Header: Root HFS0 offset: 0x%016lX", hfs0_offset); + delay(1); - snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Root HFS0 size: 0x%016lX", hfs0_size); - uiDrawString(strbuf, 0, breaks * 8, 255, 255, 255); - breaks++;*/ + uiStatusMsg("getRootHfs0Header: Root HFS0 size: 0x%016lX", hfs0_size); + delay(1);*/ hfs0_header = (char*)malloc(hfs0_size); if (!hfs0_header) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to allocate buffer!"); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: Unable to allocate memory for the root HFS0 header!"); gameCardSize = 0; memset(gameCardSizeStr, 0, sizeof(gameCardSizeStr)); @@ -151,8 +142,7 @@ bool getRootHfs0Header(FsDeviceOperator* fsOperator) if (R_FAILED(result = fsStorageRead(&gameCardStorage, hfs0_offset, hfs0_header, hfs0_size))) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "StorageRead failed! (0x%08X)", result); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: StorageRead failed to read %u-byte chunk from offset 0x%016lX! (0x%08X)", hfs0_size, hfs0_offset, result); gameCardSize = 0; memset(gameCardSizeStr, 0, sizeof(gameCardSizeStr)); @@ -171,8 +161,7 @@ bool getRootHfs0Header(FsDeviceOperator* fsOperator) if (magic != HFS0_MAGIC) { - //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Magic word mismatch! 0x%08X != 0x%08X", magic, HFS0_MAGIC); - //uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); + uiStatusMsg("getRootHfs0Header: Magic word mismatch! 0x%08X != 0x%08X", magic, HFS0_MAGIC); gameCardSize = 0; memset(gameCardSizeStr, 0, sizeof(gameCardSizeStr)); @@ -341,8 +330,6 @@ bool dumpGameCartridge(FsDeviceOperator* fsOperator, bool isFat32, bool dumpCert snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Dumping partition #%u...", partition); uiDrawString(strbuf, 0, breaks * 8, 255, 255, 255); - syncDisplay(); - workaroundPartitionZeroAccess(fsOperator); if (R_SUCCEEDED(result = fsDeviceOperatorGetGameCardHandle(fsOperator, &handle))) @@ -494,8 +481,6 @@ bool dumpGameCartridge(FsDeviceOperator* fsOperator, bool isFat32, bool dumpCert snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Writing 0xFF padding..."); uiDrawString(strbuf, 0, breaks * 8, 255, 255, 255); - syncDisplay(); - for(partitionOffset = 0; partitionOffset < paddingSize; partitionOffset += n, fileOffset += n) { if (DUMP_BUFFER_SIZE > (paddingSize - partitionOffset)) n = (paddingSize - partitionOffset); @@ -946,8 +931,6 @@ bool copyFile(const char* source, const char* dest, bool doSplitting) snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Copying \"%s\"...", source); uiDrawString(strbuf, 0, breaks * 8, 255, 255, 255); - syncDisplay(); - if ((destLen + 1) < NAME_BUF_LEN) { inFile = fopen(source, "rb"); diff --git a/source/main.c b/source/main.c index faedf99..2c229f3 100644 --- a/source/main.c +++ b/source/main.c @@ -50,6 +50,8 @@ int main(int argc, char **argv) { currentFB = gfxGetFramebuffer(¤tFBWidth, ¤tFBHeight); + uiPrintHeadline(); + gameCardInserted = isGameCardInserted(&fsOperatorInstance); if (gameCardInserted) @@ -57,13 +59,14 @@ int main(int argc, char **argv) if (hfs0_header == NULL) { // Don't access the gamecard immediately to avoid conflicts with the fs-srv, ncm and ns services - delay(1); + uiPleaseWait(); getRootHfs0Header(&fsOperatorInstance); - getGameCardTitleID(&gameCardTitleID); - getGameCardControlNacp(gameCardTitleID, gameCardName, sizeof(gameCardName), gameCardAuthor, sizeof(gameCardAuthor), gameCardVersion, sizeof(gameCardVersion)); + + uiPrintHeadline(); + uiUpdateStatusMsg(); } } else { if (hfs0_header != NULL) diff --git a/source/ui.c b/source/ui.c index 61b1a26..6606638 100644 --- a/source/ui.c +++ b/source/ui.c @@ -49,7 +49,7 @@ static char titlebuf[NAME_BUF_LEN * 2] = {'\0'}; static const int maxListElements = 45; static char *filenameBuffer = NULL; -static char *filenames[FILENAMES_COUNT_MAX]; +static char *filenames[FILENAME_MAX_CNT]; static int filenamesCount = 0; static UIState uiState; @@ -229,7 +229,7 @@ void uiDrawString(const char* string, int x, int y, u8 r, u8 g, u8 b) void uiStatusMsg(const char* format, ...) { - statusMessageFadeout = 500; + statusMessageFadeout = 1000; va_list args; va_start(args, format); vsnprintf(statusMessage, sizeof(statusMessage) / sizeof(statusMessage[0]), format, args); @@ -238,6 +238,24 @@ void uiStatusMsg(const char* format, ...) //printf("Status message: %s\n", statusMessage); } +void uiUpdateStatusMsg() +{ + if (!strlen(statusMessage) || !statusMessageFadeout) return; + + int fadeout = (statusMessageFadeout > 255 ? 255 : statusMessageFadeout); + uiFill(0, currentFBHeight - 12, currentFBWidth, 8, 50, 50, 50); + uiDrawString(statusMessage, 4, currentFBHeight - 12, fadeout, fadeout, fadeout); + statusMessageFadeout -= 4; +} + +void uiPleaseWait() +{ + breaks = headlineCnt; + uiDrawString("Please wait...", 0, breaks * 8, 115, 115, 255); + syncDisplay(); + delay(2); +} + void uiUpdateFreeSpace() { getSdCardFreeSpace(&freeSpace); @@ -255,7 +273,7 @@ void uiInit() scroll = 0; headlineCnt = 0; - filenameBuffer = (char*)malloc(FILENAMEBUFFER_SIZE); + filenameBuffer = (char*)malloc(FILENAME_BUFFER_SIZE); int i, headlineLen = strlen(appHeadline); for(i = 0; i < headlineLen; i++) @@ -292,11 +310,17 @@ void uiClearScreen() uiFill(0, 0, currentFBWidth, currentFBHeight, 50, 50, 50); } +void uiPrintHeadline() +{ + uiClearScreen(); + uiDrawString(appHeadline, 0, 0, 255, 255, 255); +} + static void enterDirectory(const char *path) { snprintf(currentDirectory, sizeof(currentDirectory) / sizeof(currentDirectory[0]), "%s", path); - filenamesCount = FILENAMES_COUNT_MAX; + filenamesCount = FILENAME_MAX_CNT; getDirectoryContents(filenameBuffer, &filenames[0], &filenamesCount, currentDirectory, (!strcmp(currentDirectory, "view:/") && strlen(currentDirectory) == 6)); cursor = 0; @@ -307,9 +331,6 @@ UIResult uiLoop(u32 keysDown) { UIResult res = resultNone; - uiClearScreen(); - uiDrawString(appHeadline, 0, 0, 255, 255, 255); - int i; breaks = headlineCnt; @@ -326,7 +347,7 @@ UIResult uiLoop(u32 keysDown) if (uiState != stateViewGameCardFsBrowser) { - if (gameCardInserted && hfs0_header != NULL && (hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT || hfs0_partition_cnt == GAMECARD_TYPE2_PARTITION_CNT)) + if (gameCardInserted && hfs0_header != NULL && (hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT || hfs0_partition_cnt == GAMECARD_TYPE2_PARTITION_CNT) && gameCardTitleID != 0) { uiDrawString("Game Card is inserted!", 0, breaks * 8, 0, 255, 0); breaks += 2; @@ -372,8 +393,13 @@ UIResult uiLoop(u32 keysDown) { if (hfs0_header != NULL) { - snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Error: unknown root HFS0 header partition count! (%u)", hfs0_partition_cnt); - uiDrawString(titlebuf, 0, breaks * 8, 255, 0, 0); + if (hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT || hfs0_partition_cnt == GAMECARD_TYPE2_PARTITION_CNT) + { + uiDrawString("Error: unable to retrieve the game card Title ID!", 0, breaks * 8, 255, 0, 0); + } else { + snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Error: unknown root HFS0 header partition count! (%u)", hfs0_partition_cnt); + uiDrawString(titlebuf, 0, breaks * 8, 255, 0, 0); + } } else { uiDrawString("Error: unable to get root HFS0 header data!", 0, breaks * 8, 255, 0, 0); } @@ -387,7 +413,7 @@ UIResult uiLoop(u32 keysDown) breaks += 2; } - if (gameCardInserted && hfs0_header != NULL && (hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT || hfs0_partition_cnt == GAMECARD_TYPE2_PARTITION_CNT)) + if (gameCardInserted && hfs0_header != NULL && (hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT || hfs0_partition_cnt == GAMECARD_TYPE2_PARTITION_CNT) && gameCardTitleID != 0) { const char **menu = NULL; int menuItemsCount; @@ -719,12 +745,7 @@ UIResult uiLoop(u32 keysDown) res = resultShowMainMenu; } - if (statusMessageFadeout > 0) - { - int fadeout = (statusMessageFadeout > 255 ? 255 : statusMessageFadeout); - uiDrawString(statusMessage, 4, currentFBHeight - 12, fadeout, fadeout, fadeout); - statusMessageFadeout -= 4; - } - + uiUpdateStatusMsg(); + return res; } diff --git a/source/ui.h b/source/ui.h index dc6d07b..4245365 100644 --- a/source/ui.h +++ b/source/ui.h @@ -3,8 +3,8 @@ #ifndef __UI_H__ #define __UI_H__ -#define FILENAMEBUFFER_SIZE (1024 * 32) // 32 KiB -#define FILENAMES_COUNT_MAX 2048 +#define FILENAME_BUFFER_SIZE (1024 * 32) // 32 KiB +#define FILENAME_MAX_CNT 2048 typedef enum { resultNone, @@ -38,10 +38,14 @@ typedef enum { stateDumpGameCardCertificate } UIState; -void uiStatusMsg(const char* fmt, ...); void uiFill(int x, int y, int width, int height, u8 r, u8 g, u8 b); void uiDrawString(const char* string, int x, int y, u8 r, u8 g, u8 b); +void uiStatusMsg(const char* fmt, ...); +void uiUpdateStatusMsg(); + +void uiPleaseWait(); + void uiUpdateFreeSpace(); void uiInit(); @@ -51,6 +55,7 @@ void uiSetState(UIState state); UIState uiGetState(); void uiClearScreen(); +void uiPrintHeadline(); UIResult uiLoop(u32 keysDown); diff --git a/source/util.c b/source/util.c index def8d5a..29f1664 100644 --- a/source/util.c +++ b/source/util.c @@ -61,21 +61,21 @@ bool getGameCardTitleID(u64 *titleID) *titleID = appList->meta_record.titleID; success = true; } else { - uiStatusMsg("MetaDatabaseListApplication failed! (0x%08x)", result); + uiStatusMsg("getGameCardTitleID: MetaDatabaseListApplication failed! (0x%08x)", result); } } else { - uiStatusMsg("GetContentMetaDatabase failed! (0x%08x)", result); + uiStatusMsg("getGameCardTitleID: GetContentMetaDatabase failed! (0x%08x)", result); } } else { - uiStatusMsg("OpenContentMetaDatabase failed! (0x%08x)", result); + uiStatusMsg("getGameCardTitleID: OpenContentMetaDatabase failed! (0x%08x)", result); } // Seems to cause problems - //if (R_FAILED(result = ncmCloseContentMetaDatabase(FsStorageId_GameCard))) uiStatusMsg("CloseContentMetaDatabase failed! (0x%08x)", result); + //if (R_FAILED(result = ncmCloseContentMetaDatabase(FsStorageId_GameCard))) uiStatusMsg("getGameCardTitleID: CloseContentMetaDatabase failed! (0x%08x)", result); free(appList); } else { - uiStatusMsg("Unable to allocate memory for the NCM service operations."); + uiStatusMsg("getGameCardTitleID: Unable to allocate memory for the NCM service operations."); } return success; @@ -103,25 +103,23 @@ bool getGameCardControlNacp(u64 titleID, char *nameBuf, int nameBufSize, char *a if (R_SUCCEEDED(result = nacpGetLanguageEntry(&buf->nacp, &langentry))) { strncpy(nameBuf, langentry->name, nameBufSize - 1); - strncpy(authorBuf, langentry->author, authorBufSize - 1); - strncpy(versionBuf, buf->nacp.version, versionBufSize - 1); success = true; } else { - uiStatusMsg("GetLanguageEntry failed! (0x%08x)", result); + uiStatusMsg("getGameCardControlNacp: GetLanguageEntry failed! (0x%08x)", result); } } else { - uiStatusMsg("Control.nacp buffer size (%u bytes) is too small! Expected: %u bytes", outsize, sizeof(buf->nacp)); + uiStatusMsg("getGameCardControlNacp: Control.nacp buffer size (%u bytes) is too small! Expected: %u bytes", outsize, sizeof(buf->nacp)); } } else { - uiStatusMsg("GetApplicationControlData failed! (0x%08x)", result); + uiStatusMsg("getGameCardControlNacp: GetApplicationControlData failed! (0x%08x)", result); } free(buf); } else { - uiStatusMsg("Unable to allocate memory for the NS service operations."); + uiStatusMsg("getGameCardControlNacp: Unable to allocate memory for the NS service operations."); } return success; @@ -135,7 +133,7 @@ int getSdCardFreeSpace(u64 *out) rc = statvfs("sdmc:/", &st); if (rc != 0) { - uiStatusMsg("Unable to get SD card filesystem stats! statvfs: %d (%s).", errno, strerror(errno)); + uiStatusMsg("getSdCardFreeSpace: Unable to get SD card filesystem stats! statvfs: %d (%s).", errno, strerror(errno)); } else { *out = (u64)(st.f_bsize * st.f_bfree); } diff --git a/source/util.h b/source/util.h index 04fec63..774875b 100644 --- a/source/util.h +++ b/source/util.h @@ -5,7 +5,7 @@ #include -#define APP_VERSION "1.0.0" +#define APP_VERSION "1.0.1" #define NAME_BUF_LEN 4096 bool isGameCardInserted(FsDeviceOperator* o);