diff --git a/Makefile b/Makefile index 3163c6d..1fccd92 100644 --- a/Makefile +++ b/Makefile @@ -33,7 +33,7 @@ include $(DEVKITPRO)/libnx/switch_rules VERSION_MAJOR := 1 VERSION_MINOR := 0 -VERSION_MICRO := 5 +VERSION_MICRO := 6 APP_TITLE := gcdumptool APP_AUTHOR := MCMrARM, DarkMatterCore @@ -56,8 +56,8 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \ $(ARCH) $(DEFINES) CFLAGS += $(INCLUDE) -D__SWITCH__ -D__LINUX_ERRNO_EXTENSIONS__ -CFLAGS += `aarch64-none-elf-pkg-config libxml-2.0 --cflags` CFLAGS += `aarch64-none-elf-pkg-config zlib --cflags` +CFLAGS += `aarch64-none-elf-pkg-config libxml-2.0 --cflags` CFLAGS += `aarch64-none-elf-pkg-config json-c --cflags` CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 @@ -65,7 +65,7 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) -LIBS := -lcurl -lz -lnx -ljson-c -lxml2 -lm +LIBS := -lcurl -lxml2 -lz -lnx -ljson-c -lm #--------------------------------------------------------------------------------- # list of directories containing libraries, this must be the top level containing diff --git a/source/dumper.c b/source/dumper.c index 9c97c2c..9f27fdc 100644 --- a/source/dumper.c +++ b/source/dumper.c @@ -1529,6 +1529,8 @@ bool dumpPartitionData(FsDeviceOperator* fsOperator, u32 partition) snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "fsdevMountDevice failed! (%d)", ret); uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); } + + fsFsClose(&fs); } else { snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "Failed to open partition #%u filesystem!", partition); uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); @@ -1539,17 +1541,16 @@ bool dumpPartitionData(FsDeviceOperator* fsOperator, u32 partition) return success; } -bool mountViewPartition(FsDeviceOperator *fsOperator, u32 partition) +bool mountViewPartition(FsDeviceOperator *fsOperator, FsFileSystem *out, u32 partition) { - FsFileSystem fs; int ret; bool success = false; workaroundPartitionZeroAccess(fsOperator); - if (openPartitionFs(&fs, fsOperator, partition)) + if (openPartitionFs(out, fsOperator, partition)) { - ret = fsdevMountDevice("view", fs); + ret = fsdevMountDevice("view", *out); if (ret != -1) { //snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "fsdevMountDevice succeeded: %d", ret); @@ -1558,6 +1559,7 @@ bool mountViewPartition(FsDeviceOperator *fsOperator, u32 partition) success = true; } else { + fsFsClose(out); snprintf(strbuf, sizeof(strbuf) / sizeof(strbuf[0]), "fsdevMountDevice failed! (%d)", ret); uiDrawString(strbuf, 0, breaks * 8, 255, 0, 0); } diff --git a/source/dumper.h b/source/dumper.h index 953b997..76e5260 100644 --- a/source/dumper.h +++ b/source/dumper.h @@ -83,7 +83,7 @@ bool copyDirectory(const char* source, const char* dest, bool doSplitting); void removeDirectory(const char *path); bool getDirectorySize(const char *path, u64 *out_size); bool dumpPartitionData(FsDeviceOperator* fsOperator, u32 partition); -bool mountViewPartition(FsDeviceOperator *fsOperator, u32 partition); +bool mountViewPartition(FsDeviceOperator *fsOperator, FsFileSystem *out, u32 partition); bool dumpGameCertificate(FsDeviceOperator *fsOperator); #endif diff --git a/source/fsext.c b/source/fsext.c index 46c1899..81fead6 100644 --- a/source/fsext.c +++ b/source/fsext.c @@ -15,7 +15,7 @@ Result fsOpenGameCardStorage(FsStorage* out, u32 handle, u32 partition) u64 cmd_id; u32 handle; u32 partition; - } PACKED *raw; + } *raw; raw = ipcPrepareHeader(&c, sizeof(*raw)); @@ -54,7 +54,7 @@ Result fsOpenGameCardFileSystem(FsFileSystem* out, u32 handle, u32 partition) u64 cmd_id; u32 handle; u32 partition; - } PACKED *raw; + } *raw; raw = ipcPrepareHeader(&c, sizeof(*raw)); @@ -198,40 +198,3 @@ Result fsDeviceOperatorUpdatePartitionInfo(FsDeviceOperator* d, u32 handle, u32* return rc; } - -// FsStorage -Result fsStorageGetSize(FsStorage* s, u64* out) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 4; - - Result rc = serviceIpcDispatch(&s->s); - - if (R_SUCCEEDED(rc)) - { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - u64 size; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) *out = resp->size; - } - - return rc; -} diff --git a/source/main.c b/source/main.c index a9114f7..04f2fb4 100644 --- a/source/main.c +++ b/source/main.c @@ -4,7 +4,6 @@ #include #include "dumper.h" -#include "ncmext.h" #include "ui.h" #include "util.h" diff --git a/source/ncmext.c b/source/ncmext.c deleted file mode 100644 index ee13544..0000000 --- a/source/ncmext.c +++ /dev/null @@ -1,170 +0,0 @@ -#include -#include -#include -#include - -#include "ncmext.h" - -static Service g_ncm; -static u64 g_refCnt; - -// IContentManager -Result ncmInitialize(void) -{ - atomicIncrement64(&g_refCnt); - - if (serviceIsActive(&g_ncm)) return 0; - - Result rc = smGetService(&g_ncm, "ncm"); - - return rc; -} - -void ncmExit(void) -{ - if (atomicDecrement64(&g_refCnt) == 0) serviceClose(&g_ncm); -} - -Result ncmGetContentMetaDatabase(ncmContentMetaDatabase *out, FsStorageId storage_id) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 5; - raw->storage_id = storage_id; - - Result rc = serviceIpcDispatch(&g_ncm); - - if (R_SUCCEEDED(rc)) - { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - - if (R_SUCCEEDED(rc)) serviceCreate(&out->s, r.Handles[0]); - } - - return rc; -} - -Result ncmOpenContentMetaDatabase(FsStorageId storage_id) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 11; - raw->storage_id = storage_id; - - Result rc = serviceIpcDispatch(&g_ncm); - - if (R_SUCCEEDED(rc)) - { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -Result ncmCloseContentMetaDatabase(FsStorageId storage_id) -{ - IpcCommand c; - ipcInitialize(&c); - - struct { - u64 magic; - u64 cmd_id; - u8 storage_id; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 12; - raw->storage_id = storage_id; - - Result rc = serviceIpcDispatch(&g_ncm); - - if (R_SUCCEEDED(rc)) - { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} - -// IContentMetaDatabase -Result ncmMetaDatabaseListApplication(ncmContentMetaDatabase *md, ncmApplicationMetaKey *buffer, size_t size, u8 filter) -{ - IpcCommand c; - ipcInitialize(&c); - ipcAddRecvBuffer(&c, buffer, size, BufferType_Normal); - - struct { - u64 magic; - u64 cmd_id; - u8 filter; - } *raw; - - raw = ipcPrepareHeader(&c, sizeof(*raw)); - - raw->magic = SFCI_MAGIC; - raw->cmd_id = 7; - raw->filter = filter; - - Result rc = serviceIpcDispatch(&md->s); - - if (R_SUCCEEDED(rc)) - { - IpcParsedCommand r; - ipcParse(&r); - - struct { - u64 magic; - u64 result; - } *resp = r.Raw; - - rc = resp->result; - } - - return rc; -} diff --git a/source/ncmext.h b/source/ncmext.h deleted file mode 100644 index d559ea1..0000000 --- a/source/ncmext.h +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#ifndef __NCMEXT_H__ -#define __NCMEXT_H__ - -#include -#include - -typedef struct { - Service s; -} ncmContentMetaDatabase; - -typedef struct { - u64 titleID; - u32 titleVersion; - u8 type; - u8 unk1; - u16 unk2; -} ncmContentMetaKey; - -typedef struct { - ncmContentMetaKey meta_record; - u64 base_title_id; -} ncmApplicationMetaKey; - -// IContentManager -Result ncmInitialize(void); -void ncmExit(void); -Result ncmGetContentMetaDatabase(ncmContentMetaDatabase *out, FsStorageId storage_id); -Result ncmOpenContentMetaDatabase(FsStorageId storage_id); -Result ncmCloseContentMetaDatabase(FsStorageId storage_id); - -// IContentMetaDatabase -Result ncmMetaDatabaseListApplication(ncmContentMetaDatabase *md, ncmApplicationMetaKey *buffer, size_t size, u8 filter); - -#endif diff --git a/source/ui.c b/source/ui.c index 0a9c5cf..68fa9f6 100644 --- a/source/ui.c +++ b/source/ui.c @@ -35,6 +35,8 @@ static bool isFat32 = false, dumpCert = false, trimDump = false, calcCrc = true; static u32 selectedOption; +static FsFileSystem fs; + static char statusMessage[2048] = {'\0'}; static int statusMessageFadeout = 0; @@ -60,14 +62,14 @@ static int filenamesCount = 0; static UIState uiState; static const char *appHeadline = "Nintendo Switch Game Card Dump Tool v" APP_VERSION ".\nOriginal code by MCMrARM.\nAdditional modifications by DarkMatterCore.\n\n"; -static const char *appControls = "[D-Pad / Analog Stick] Move | [A] Select | [B] Back | [+] Exit"; +static const char *appControls = "[D-Pad / Analog Sticks] Move | [A] Select | [B] Back | [+] Exit"; -static const char *mainMenuItems[] = { "Full XCI Dump", "Raw Partition Dump", "Partition Data Dump", "View Game Card Files", "Dump Game Card Certificate", "Update nswdb.com XML database", "Update application (not working at this moment)" }; +static const char *mainMenuItems[] = { "Full XCI dump", "Raw partition dump", "Partition data dump", "View game card files", "Dump game card certificate", "Update NSWDB.COM XML database", "Update application (not working at this moment)" }; static const char *xciDumpMenuItems[] = { "Start XCI dump process", "Split output dump (FAT32 support): ", "Dump certificate: ", "Trim output dump: ", "CRC32 checksum calculation + dump verification: " }; -static const char *partitionDumpType1MenuItems[] = { "Dump Partition 0 (Update)", "Dump Partition 1 (Normal)", "Dump Partition 2 (Secure)" }; -static const char *partitionDumpType2MenuItems[] = { "Dump Partition 0 (Update)", "Dump Partition 1 (Logo)", "Dump Partition 2 (Normal)", "Dump Partition 3 (Secure)" }; -static const char *viewGameCardFsType1MenuItems[] = { "View Files from Partition 0 (Update)", "View Files from Partition 1 (Normal)", "View Files from Partition 2 (Secure)" }; -static const char *viewGameCardFsType2MenuItems[] = { "View Files from Partition 0 (Update)", "View Files from Partition 1 (Logo)", "View Files from Partition 2 (Normal)", "View Files from Partition 3 (Secure)" }; +static const char *partitionDumpType1MenuItems[] = { "Dump partition 0 (Update)", "Dump partition 1 (Normal)", "Dump partition 2 (Secure)" }; +static const char *partitionDumpType2MenuItems[] = { "Dump partition 0 (Update)", "Dump partition 1 (Logo)", "Dump partition 2 (Normal)", "Dump partition 3 (Secure)" }; +static const char *viewGameCardFsType1MenuItems[] = { "View files from partition 0 (Update)", "View files from partition 1 (Normal)", "View files from partition 2 (Secure)" }; +static const char *viewGameCardFsType2MenuItems[] = { "View files from partition 0 (Update)", "View files from partition 1 (Logo)", "View files from partition 2 (Normal)", "View files from partition 3 (Secure)" }; static unsigned char asciiData[128][8] = { {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, {0x00, 0x3E, 0x41, 0x55, 0x41, 0x55, 0x49, 0x3E}, @@ -294,8 +296,6 @@ void uiInit() void uiDeinit() { if (filenameBuffer) free(filenameBuffer); - - if (uiState == stateViewGameCardFsBrowser) fsdevUnmountDevice("view"); } void uiSetState(UIState state) @@ -342,7 +342,16 @@ UIResult uiLoop(u32 keysDown) if (uiState == stateMainMenu || uiState == stateXciDumpMenu || uiState == stateRawPartitionDumpMenu || uiState == statePartitionDataDumpMenu || uiState == stateViewGameCardFsMenu || uiState == stateViewGameCardFsBrowser) { // Exit - if (keysDown & KEY_PLUS) return resultExit; + if (keysDown & KEY_PLUS) + { + if (uiState == stateViewGameCardFsBrowser) + { + fsdevUnmountDevice("view"); + fsFsClose(&fs); + } + + return resultExit; + } uiDrawString(appControls, 0, breaks * 8, 255, 255, 255); breaks += 2; @@ -395,7 +404,7 @@ UIResult uiLoop(u32 keysDown) if (strlen(gameCardUpdateVersionStr)) { breaks++; - snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Game Card FW Version: %s", gameCardUpdateVersionStr); + snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Bundled FW update: %s", gameCardUpdateVersionStr); uiDrawString(titlebuf, 0, breaks * 8, 0, 255, 0); } } else { @@ -410,7 +419,7 @@ UIResult uiLoop(u32 keysDown) if (strlen(gameCardUpdateVersionStr)) { breaks++; - snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Game Card FW Version: %s", gameCardUpdateVersionStr); + snprintf(titlebuf, sizeof(titlebuf) / sizeof(titlebuf[0]), "Bundled FW Update: %s", gameCardUpdateVersionStr); uiDrawString(titlebuf, 0, breaks * 8, 0, 255, 0); breaks++; @@ -722,6 +731,7 @@ UIResult uiLoop(u32 keysDown) if (!strcmp(currentDirectory, "view:/") && strlen(currentDirectory) == 6) { fsdevUnmountDevice("view"); + fsFsClose(&fs); res = resultShowViewGameCardFsMenu; } else { @@ -807,7 +817,7 @@ UIResult uiLoop(u32 keysDown) uiDrawString((hfs0_partition_cnt == GAMECARD_TYPE1_PARTITION_CNT ? viewGameCardFsType1MenuItems[selectedOption] : viewGameCardFsType1MenuItems[selectedOption]), 0, breaks * 8, 115, 115, 255); breaks += 2; - if (mountViewPartition(&fsOperatorInstance, selectedOption)) + if (mountViewPartition(&fsOperatorInstance, &fs, selectedOption)) { enterDirectory("view:/"); diff --git a/source/util.c b/source/util.c index c762bdd..6aa8d5d 100644 --- a/source/util.c +++ b/source/util.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -17,7 +18,6 @@ #include "dumper.h" #include "fsext.h" -#include "ncmext.h" #include "ui.h" #include "util.h" @@ -77,38 +77,30 @@ bool getGameCardTitleIDAndVersion(u64 *titleID, u32 *version) bool success = false; Result result; - ncmContentMetaDatabase ncmDb; + NcmContentMetaDatabase ncmDb; - ncmApplicationMetaKey *appList = (ncmApplicationMetaKey*)malloc(sizeof(ncmApplicationMetaKey)); + NcmApplicationContentMetaKey *appList = (NcmApplicationContentMetaKey*)malloc(sizeof(NcmApplicationContentMetaKey)); if (appList) { - memset(appList, 0, sizeof(ncmApplicationMetaKey)); + memset(appList, 0, sizeof(NcmApplicationContentMetaKey)); - if (R_SUCCEEDED(result = ncmOpenContentMetaDatabase(FsStorageId_GameCard))) + if (R_SUCCEEDED(result = ncmOpenContentMetaDatabase(FsStorageId_GameCard, &ncmDb))) { - if (R_SUCCEEDED(result = ncmGetContentMetaDatabase(&ncmDb, FsStorageId_GameCard))) + if (R_SUCCEEDED(result = ncmContentMetaDatabaseListApplication(&ncmDb, META_DATABASE_FILTER, appList, sizeof(NcmApplicationContentMetaKey), NULL, NULL))) { - if (R_SUCCEEDED(result = ncmMetaDatabaseListApplication(&ncmDb, appList, sizeof(ncmApplicationMetaKey), 0))) - { - *titleID = appList->meta_record.titleID; - *version = appList->meta_record.titleVersion; - success = true; - } else { - uiStatusMsg("getGameCardTitleIDAndVersion: MetaDatabaseListApplication failed! (0x%08X)", result); - } + *titleID = appList->metaRecord.titleId; + *version = appList->metaRecord.version; + success = true; } else { - uiStatusMsg("getGameCardTitleIDAndVersion: GetContentMetaDatabase failed! (0x%08X)", result); + uiStatusMsg("getGameCardTitleIDAndVersion: ncmContentMetaDatabaseListApplication failed! (0x%08X)", result); } } else { - uiStatusMsg("getGameCardTitleIDAndVersion: OpenContentMetaDatabase failed! (0x%08X)", result); + uiStatusMsg("getGameCardTitleIDAndVersion: ncmOpenContentMetaDatabase failed! (0x%08X)", result); } - // Seems to cause problems - //if (R_FAILED(result = ncmCloseContentMetaDatabase(FsStorageId_GameCard))) uiStatusMsg("getGameCardTitleIDAndVersion: CloseContentMetaDatabase failed! (0x%08X)", result); - free(appList); } else { - uiStatusMsg("getGameCardTitleIDAndVersion: Unable to allocate memory for the NCM service operations."); + uiStatusMsg("getGameCardTitleIDAndVersion: Unable to allocate memory for the ncm service operations."); } return success; @@ -147,7 +139,6 @@ bool getGameCardControlNacp(u64 titleID, char *nameBuf, int nameBufSize, char *a { strncpy(nameBuf, langentry->name, nameBufSize - 1); strncpy(authorBuf, langentry->author, authorBufSize - 1); - success = true; } else { uiStatusMsg("getGameCardControlNacp: GetLanguageEntry failed! (0x%08X)", result); @@ -161,7 +152,7 @@ bool getGameCardControlNacp(u64 titleID, char *nameBuf, int nameBufSize, char *a free(buf); } else { - uiStatusMsg("getGameCardControlNacp: Unable to allocate memory for the NS service operations."); + uiStatusMsg("getGameCardControlNacp: Unable to allocate memory for the ns service operations."); } return success; diff --git a/source/util.h b/source/util.h index a2915dd..2e91e3b 100644 --- a/source/util.h +++ b/source/util.h @@ -5,9 +5,13 @@ #include -#define APP_VERSION "1.0.5" -#define NAME_BUF_LEN 4096 -#define SOCK_BUFFERSIZE 65536 +#define APP_VERSION "1.0.6" + +#define NAME_BUF_LEN 4096 + +#define SOCK_BUFFERSIZE 65536 + +#define META_DATABASE_FILTER 0x80 // Regular Application bool isGameCardInserted(FsDeviceOperator* o);