1
0
Fork 0
mirror of https://github.com/DarkMatterCore/nxdumptool.git synced 2024-11-22 18:26:39 +00:00

Update to v1.0.1.

This commit is contained in:
Pablo Curiel 2018-06-21 20:46:17 -04:00
parent 3888e6a54c
commit a122605b6e
8 changed files with 92 additions and 68 deletions

View file

@ -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

View file

@ -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.

View file

@ -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");

View file

@ -50,6 +50,8 @@ int main(int argc, char **argv)
{
currentFB = gfxGetFramebuffer(&currentFBWidth, &currentFBHeight);
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)

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}

View file

@ -5,7 +5,7 @@
#include <switch.h>
#define APP_VERSION "1.0.0"
#define APP_VERSION "1.0.1"
#define NAME_BUF_LEN 4096
bool isGameCardInserted(FsDeviceOperator* o);