diff --git a/Makefile b/Makefile index cc75712..673154d 100644 --- a/Makefile +++ b/Makefile @@ -13,11 +13,11 @@ export TOPDIR := $(CURDIR) NITRO_FILES := # These set the information text in the nds file -GAME_TITLE := NAND Title Manager -GAME_SUBTITLE1 := JeffRuLz, Pk11 +GAME_TITLE := TAD Delivery Tool +GAME_SUBTITLE1 := JeffRuLz, Pk11, rmc -GAME_CODE := HTNA -GAME_LABEL := NANDTM_TAD +GAME_CODE := 4TDA +GAME_LABEL := TAD_DELIVERY include $(DEVKITARM)/ds_rules diff --git a/arm9/src/backupmenu.c b/arm9/src/backupmenu.c index d968f5a..6ff6603 100644 --- a/arm9/src/backupmenu.c +++ b/arm9/src/backupmenu.c @@ -157,12 +157,7 @@ static void generateList(Menu* m) } else { - if (strcasecmp(strrchr(ent->d_name, '.'), ".nds") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".app") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".dsi") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".ids") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".srl") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".cia") == 0) + if (strcasecmp(strrchr(ent->d_name, '.'), ".tad") == 0) { if (count < m->page * ITEMS_PER_PAGE) count += 1; diff --git a/arm9/src/install.c b/arm9/src/install.c index f106f2c..090b49a 100644 --- a/arm9/src/install.c +++ b/arm9/src/install.c @@ -352,7 +352,7 @@ static void _createTicket(tDSiHeader *h, char* ticketPath) } } -bool install(char* fpath, bool systemTitle) +bool install(char* tadPath, bool systemTitle) { bool result = false; @@ -365,6 +365,7 @@ bool install(char* fpath, bool systemTitle) //start installation clearScreen(&bottomScreen); + char* fpath = decryptTad(tadPath); tDSiHeader* h = getRomHeader(fpath); @@ -694,13 +695,7 @@ bool install(char* fpath, bool systemTitle) { int result = 0; - if (romIsCia(fpath)) { - result = copyFilePart(fpath, 0x3900, fileSize, appPath); - } else if (romIsTad(fpath)) { - result = decryptTad(fpath); - } else { - result = copyFile(fpath, appPath); - } + result = copyFile(fpath, appPath); if (result != 0) { diff --git a/arm9/src/installmenu.c b/arm9/src/installmenu.c index 5785efa..059d776 100644 --- a/arm9/src/installmenu.c +++ b/arm9/src/installmenu.c @@ -186,13 +186,7 @@ static void generateList(Menu* m) } else { - if (strcasecmp(strrchr(ent->d_name, '.'), ".nds") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".app") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".dsi") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".ids") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".srl") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".tad") == 0 || - strcasecmp(strrchr(ent->d_name, '.'), ".cia") == 0) + if (strcasecmp(strrchr(ent->d_name, '.'), ".tad") == 0) { if (count < m->page * ITEMS_PER_PAGE) count += 1; @@ -238,7 +232,7 @@ static void printItem(Menu* m) if (m->items[m->cursor].directory) clearScreen(&topScreen); else - printRomInfo(m->items[m->cursor].value); + printTadInfo(m->items[m->cursor].value); } static int subMenu() diff --git a/arm9/src/main.c b/arm9/src/main.c index 81d6963..bc199fa 100644 --- a/arm9/src/main.c +++ b/arm9/src/main.c @@ -11,8 +11,6 @@ bool programEnd = false; bool sdnandMode = true; bool unlaunchFound = false; bool unlaunchPatches = false; -bool devkpFound = false; -bool launcherDSiFound = false; bool arm7Exiting = false; bool charging = false; u8 batteryLevel = 0; @@ -57,32 +55,30 @@ static int _mainMenu(int cursor) //top screen clearScreen(&topScreen); - iprintf("\t\tNAND Title Manager\n"); + iprintf("\t\tTAD Delivery Tool\n"); iprintf("\t\t\tmodified from\n"); iprintf("\tTitle Manager for HiyaCFW\n"); + iprintf("\tand Nand Title Manager\n"); iprintf("\nversion %s\n", VERSION); iprintf("\n\n\x1B[41mWARNING:\x1B[47m This tool can write to\nyour internal NAND!\n\nThis always has a risk, albeit\nlow, of \x1B[41mbricking\x1B[47m your system\nand should be done with caution!\n"); iprintf("\n\t \x1B[46mhttps://dsi.cfw.guide\x1B[47m\n"); - iprintf("\n\n \x1B[46mgithub.com/Epicpkmn11/NTM/wiki\x1B[47m\n"); + iprintf("\n\n \x1B[46mgithub.com/rvtr/TDT\x1B[47m\n"); iprintf("\x1b[22;0HJeff - 2018-2019"); iprintf("\x1b[23;0HPk11 - 2022-2023"); + iprintf("\x1b[24;0Hrmc - 2024-2024"); //menu Menu* m = newMenu(); setMenuHeader(m, "MAIN MENU"); - char modeStr[32], datamanStr[32], launcherStr[32]; + char modeStr[32]; sprintf(modeStr, "Mode: %s", sdnandMode ? "SDNAND" : "\x1B[41mSysNAND\x1B[47m"); - sprintf(datamanStr, "\x1B[%02omEnable Data Management", devkpFound ? 037 : 047); - sprintf(launcherStr, "\x1B[%02omUninstall region mod", launcherDSiFound ? 047 : 037); addMenuItem(m, modeStr, NULL, 0); addMenuItem(m, "Install", NULL, 0); addMenuItem(m, "Titles", NULL, 0); - addMenuItem(m, "Restore", NULL, 0); + //addMenuItem(m, "Restore", NULL, 0); addMenuItem(m, "Test", NULL, 0); addMenuItem(m, "Fix FAT copy mismatch", NULL, 0); - addMenuItem(m, datamanStr, NULL, 0); - addMenuItem(m, launcherStr, NULL, 0); addMenuItem(m, "\x1B[47mExit", NULL, 0); m->cursor = cursor; @@ -207,19 +203,13 @@ int main(int argc, char **argv) } else if (!unlaunchPatches) { - messageBox("Unlaunch's Launcher Patches are\nnot enabled. You will need to\nprovide TMD files or reinstall.\n\n\x1B[46mhttps://dsi.cfw.guide/\x1B[47m"); + messageBox("Unlaunch's Launcher Patches are\nnot enabled. You will need these\nif you patch any TADs.\n\n\x1B[46mhttps://dsi.cfw.guide/\x1B[47m"); } } - //check for dev.kp (Data Management visible) - devkpFound = (access("sd:/sys/dev.kp", F_OK) == 0); - - //check for launcher.dsi (Language patcher) - launcherDSiFound = (access("nand:/launcher.dsi", F_OK) == 0); - messageBox("\x1B[41mWARNING:\x1B[47m This tool can write to\nyour internal NAND!\n\nThis always has a risk, albeit\nlow, of \x1B[41mbricking\x1B[47m your system\nand should be done with caution!\n\nIf you have not yet done so,\nyou should make a NAND backup."); - messageBox("If you are following a video\nguide, please stop.\n\nVideo guides for console moddingare often outdated or straight\nup incorrect to begin with.\n\nThe recommended guide for\nmodding your DSi is:\n\n\x1B[46mhttps://dsi.cfw.guide/\x1B[47m\n\nFor more information on using\nNTM, see the official wiki:\n\n\x1B[46mhttps://github.com/Epicpkmn11/\n\t\t\t\t\t\t\t\tNTM/wiki\x1B[47m"); + messageBox("If you are following a video\nguide, please stop.\n\nVideo guides for console moddingare often outdated or straight\nup incorrect to begin with.\n\nThe recommended guide for\nmodding your DSi is:\n\n\x1B[46mhttps://dsi.cfw.guide/\x1B[47m\n\nFor more information on using\nTDT, see the official repo:\n\n\x1B[46mhttps://github.com/rvtr/TDT\x1B[47m"); //main menu int cursor = 0; @@ -231,7 +221,6 @@ int main(int argc, char **argv) { case MAIN_MENU_MODE: sdnandMode = !sdnandMode; - devkpFound = (access(sdnandMode ? "sd:/sys/dev.kp" : "nand:/sys/dev.kp", F_OK) == 0); break; case MAIN_MENU_INSTALL: @@ -241,11 +230,11 @@ int main(int argc, char **argv) case MAIN_MENU_TITLES: titleMenu(); break; - + /* case MAIN_MENU_BACKUP: backupMenu(); break; - + */ case MAIN_MENU_TEST: testMenu(); break; @@ -259,35 +248,6 @@ int main(int argc, char **argv) } break; - case MAIN_MENU_DATA_MANAGEMENT: - if (!devkpFound && (choiceBox("Make Data Management visible\nin System Settings?") == YES) && (sdnandMode || nandio_unlock_writing())) - { - //ensure sys folder exists - if(access(sdnandMode ? "sd:/sys" : "nand:/sys", F_OK) != 0) - mkdir(sdnandMode ? "sd:/sys" : "nand:/sys", 0777); - - //create empty file - FILE *file = fopen(sdnandMode ? "sd:/sys/dev.kp" : "nand:/sys/dev.kp", "wb"); - fclose(file); - - if(!sdnandMode) - nandio_lock_writing(); - devkpFound = (access(sdnandMode ? "sd:/sys/dev.kp" : "nand:/sys/dev.kp", F_OK) == 0); - messageBox("Data Management is now visible\nin System Settings.\n"); - } - break; - case MAIN_MENU_LANGUAGE_PATCHER: - if (launcherDSiFound && (choiceBox("Uninstall the language patched\nDSi Menu? (launcher.dsi)") == YES) && nandio_unlock_writing()) - { - //delete launcher.dsi - remove("nand:/launcher.dsi"); - - nandio_lock_writing(); - launcherDSiFound = (access("nand:/launcher.dsi", F_OK) == 0); - messageBox("The language patched DSi Menu\nhas been removed.\n"); - } - break; - case MAIN_MENU_EXIT: programEnd = true; break; diff --git a/arm9/src/rom.c b/arm9/src/rom.c index 2c6e870..5fb99e3 100644 --- a/arm9/src/rom.c +++ b/arm9/src/rom.c @@ -1,6 +1,7 @@ #include "rom.h" #include "main.h" #include "storage.h" +#include "tad.h" #include #include #include @@ -19,11 +20,7 @@ tDSiHeader* getRomHeader(char const* fpath) if (h) { - if (romIsCia(fpath)) - fseek(f, 0x3900, SEEK_SET); - else - fseek(f, 0, SEEK_SET); - + fseek(f, 0, SEEK_SET); fread(h, sizeof(tDSiHeader), 1, f); } @@ -50,11 +47,7 @@ tNDSBanner* getRomBanner(char const* fpath) if (b) { - if (romIsCia(fpath)) - fseek(f, 0x3900, SEEK_SET); - else - fseek(f, 0, SEEK_SET); - + fseek(f, 0, SEEK_SET); fseek(f, h->ndshdr.bannerOffset, SEEK_CUR); fread(b, sizeof(tNDSBanner), 1, f); } @@ -146,106 +139,99 @@ void printRomInfo(char const* fpath) tDSiHeader* h = getRomHeader(fpath); tNDSBanner* b = getRomBanner(fpath); - if (!isDsiHeader(h)) + if (!b) { - iprintf("Could not read dsi header.\n"); + iprintf("Could not read banner.\n"); } else { - if (!b) + //proper title { - iprintf("Could not read banner.\n"); + char gameTitle[128+1]; + getGameTitle(b, gameTitle, true); + + iprintf("%s\n\n", gameTitle); } - else + + //file size { - //proper title - { - char gameTitle[128+1]; - getGameTitle(b, gameTitle, true); - - iprintf("%s\n\n", gameTitle); - } - - //file size - { - iprintf("Size: "); - unsigned long long romSize = getRomSize(fpath); - printBytes(romSize); - //size in blocks, rounded up - iprintf(" (%lld blocks)\n", ((romSize / BYTES_PER_BLOCK) * BYTES_PER_BLOCK + BYTES_PER_BLOCK) / BYTES_PER_BLOCK); - } - - iprintf("Label: %.12s\n", h->ndshdr.gameTitle); - iprintf("Game Code: %.4s\n", h->ndshdr.gameCode); - - //system type - { - iprintf("Unit Code: "); - - switch (h->ndshdr.unitCode) - { - case 0: iprintf("NDS"); break; - case 2: iprintf("NDS+DSi"); break; - case 3: iprintf("DSi"); break; - default: iprintf("unknown"); - } - - iprintf("\n"); - } - - //application type - { - iprintf("Program Type: "); - - switch (h->ndshdr.reserved1[7]) - { - case 0x3: iprintf("Normal"); break; - case 0xB: iprintf("Sys"); break; - case 0xF: iprintf("Debug/Sys"); break; - default: iprintf("unknown"); - } - - iprintf("\n"); - } - - //DSi title ids - { - if (h->tid_high == 0x00030004 || - h->tid_high == 0x00030005 || - h->tid_high == 0x00030011 || // TID for software in TWL SDK - h->tid_high == 0x00030015 || - h->tid_high == 0x00030017 || - h->tid_high == 0x00030000) - { - iprintf("Title ID: %08x %08x\n", (unsigned int)h->tid_high, (unsigned int)h->tid_low); - } - } - - //print full file path - iprintf("\n%s\n", fpath); - - //print extra files - int extensionPos = strrchr(fpath, '.') - fpath; - char temp[PATH_MAX]; - strcpy(temp, fpath); - strcpy(temp + extensionPos, ".tmd"); - //DSi TMDs are 520, TMDs from NUS are 2,312. If 2,312 we can simply trim it to 520 - int tmdSize = getFileSizePath(temp); - if (access(temp, F_OK) == 0) - printf("\t\x1B[%om%s\n\x1B[47m", (tmdSize == 520 || tmdSize == 2312) ? 047 : 041, strrchr(temp, '/') + 1); - - strcpy(temp + extensionPos, ".pub"); - if (access(temp, F_OK) == 0) - printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == h->public_sav_size) ? 047 : 041, strrchr(temp, '/') + 1); - - strcpy(temp + extensionPos, ".prv"); - if (access(temp, F_OK) == 0) - printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == h->private_sav_size) ? 047 : 041, strrchr(temp, '/') + 1); - - strcpy(temp + extensionPos, ".bnr"); - if (access(temp, F_OK) == 0) - printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == 0x4000) ? 047 : 041, strrchr(temp, '/') + 1); + iprintf("Size: "); + unsigned long long romSize = getRomSize(fpath); + printBytes(romSize); + //size in blocks, rounded up + iprintf(" (%lld blocks)\n", ((romSize / BYTES_PER_BLOCK) * BYTES_PER_BLOCK + BYTES_PER_BLOCK) / BYTES_PER_BLOCK); } + + iprintf("Label: %.12s\n", h->ndshdr.gameTitle); + iprintf("Game Code: %.4s\n", h->ndshdr.gameCode); + + //system type + { + iprintf("Unit Code: "); + + switch (h->ndshdr.unitCode) + { + case 0: iprintf("NDS"); break; + case 2: iprintf("NDS+DSi"); break; + case 3: iprintf("DSi"); break; + default: iprintf("unknown"); + } + + iprintf("\n"); + } + + //application type + { + iprintf("Program Type: "); + + switch (h->ndshdr.reserved1[7]) + { + case 0x3: iprintf("Normal"); break; + case 0xB: iprintf("Sys"); break; + case 0xF: iprintf("Debug/Sys"); break; + default: iprintf("unknown"); + } + + iprintf("\n"); + } + + //DSi title ids + { + if (h->tid_high == 0x00030004 || + h->tid_high == 0x00030005 || + h->tid_high == 0x00030011 || // TID for software in TWL SDK + h->tid_high == 0x00030015 || + h->tid_high == 0x00030017 || + h->tid_high == 0x00030000) + { + iprintf("Title ID: %08x %08x\n", (unsigned int)h->tid_high, (unsigned int)h->tid_low); + } + } + + //print full file path + iprintf("\n%s\n", fpath); + + //print extra files + int extensionPos = strrchr(fpath, '.') - fpath; + char temp[PATH_MAX]; + strcpy(temp, fpath); + strcpy(temp + extensionPos, ".tmd"); + //DSi TMDs are 520, TMDs from NUS are 2,312. If 2,312 we can simply trim it to 520 + int tmdSize = getFileSizePath(temp); + if (access(temp, F_OK) == 0) + printf("\t\x1B[%om%s\n\x1B[47m", (tmdSize == 520 || tmdSize == 2312) ? 047 : 041, strrchr(temp, '/') + 1); + + strcpy(temp + extensionPos, ".pub"); + if (access(temp, F_OK) == 0) + printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == h->public_sav_size) ? 047 : 041, strrchr(temp, '/') + 1); + + strcpy(temp + extensionPos, ".prv"); + if (access(temp, F_OK) == 0) + printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == h->private_sav_size) ? 047 : 041, strrchr(temp, '/') + 1); + + strcpy(temp + extensionPos, ".bnr"); + if (access(temp, F_OK) == 0) + printf("\t\x1B[%om%s\n\x1B[47m", (getFileSizePath(temp) == 0x4000) ? 047 : 041, strrchr(temp, '/') + 1); } free(b); @@ -261,42 +247,10 @@ unsigned long long getRomSize(char const* fpath) if (f) { - //cia - if (romIsCia(fpath)) - { - unsigned char bytes[4] = { 0 }; - fseek(f, 0x38D0, SEEK_SET); - fread(bytes, 4, 1, f); - size = (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; - } - else - { - fseek(f, 0, SEEK_END); - size = ftell(f); - } + fseek(f, 0, SEEK_END); + size = ftell(f); } fclose(f); return size; -} - -bool romIsCia(char const* fpath) -{ - if (!fpath) return false; - return (strstr(fpath, ".cia") != NULL || strstr(fpath, ".CIA") != NULL); -} - -bool romIsTad(char const* fpath) -{ - if (!fpath) return false; - return (strstr(fpath, ".tad") != NULL || strstr(fpath, ".TAD") != NULL); -} - -bool isDsiHeader(tDSiHeader* h) -{ - if (!h) return false; - - u16 crc16 = swiCRC16(0xFFFF, h, 0x15E); - - return h->ndshdr.headerCRC16 == crc16; } \ No newline at end of file diff --git a/arm9/src/rom.h b/arm9/src/rom.h index 9fc07d5..122cdf7 100644 --- a/arm9/src/rom.h +++ b/arm9/src/rom.h @@ -17,7 +17,6 @@ void printRomInfo(char const* fpath); unsigned long long getRomSize(char const* fpath); -bool romIsCia(char const* fpath); -bool isDsiHeader(tDSiHeader* h); +bool romIsSrl(char const* fpath); #endif \ No newline at end of file diff --git a/arm9/src/storage.c b/arm9/src/storage.c index 827c286..7234a1a 100644 --- a/arm9/src/storage.c +++ b/arm9/src/storage.c @@ -440,6 +440,7 @@ int getMenuSlotsFree() const char* dirs[] = { "00030004", "00030005", + "0003000f", "00030015", "00030017" }; diff --git a/arm9/src/tad.c b/arm9/src/tad.c index 1063cd3..d3636af 100644 --- a/arm9/src/tad.c +++ b/arm9/src/tad.c @@ -7,6 +7,8 @@ #include "tad.h" #include "storage.h" +#include "rom.h" +#include "main.h" #include "nand/twltool/dsi.h" #include #include @@ -41,6 +43,7 @@ const unsigned char debuggerKey[] = { 0xA2, 0xFD, 0xDD, 0xF2 ,0xE4, 0x23, 0x57, 0x4A, 0xE7, 0xED, 0x86, 0x57, 0xB5, 0xAB, 0x19, 0xD3 }; + typedef struct { uint32_t hdrSize; uint16_t tadType; @@ -174,7 +177,7 @@ int decryptTad(char const* src) iprintf("\n--------------------------------\nCopying output files:\n"); // Sorry for copy pasting, I'll make this a routine later iprintf(" Copying TMD...\n"); - FILE *tmdFile = fopen("sd:/_nds/tadtests/tmp/tmd.srl", "wb"); + FILE *tmdFile = fopen("sd:/_nds/tadtests/tmp/temp.tmd", "wb"); fseek(file, tad.tmdOffset, SEEK_SET); for (int i = 0; i < swap_endian_u32(header.tmdSize); i++) { char ch = fgetc(file); @@ -183,7 +186,7 @@ int decryptTad(char const* src) fclose(tmdFile); iprintf(" Copying ticket...\n"); - FILE *ticketFile = fopen("sd:/_nds/tadtests/tmp/ticket.srl", "wb"); + FILE *ticketFile = fopen("sd:/_nds/tadtests/tmp/temp.tik", "wb"); fseek(file, tad.ticketOffset, SEEK_SET); for (int i = 0; i < swap_endian_u32(header.ticketSize); i++) { char ch = fgetc(file); @@ -192,7 +195,7 @@ int decryptTad(char const* src) fclose(ticketFile); iprintf(" Copying SRL...\n"); - FILE *srlFile = fopen("sd:/_nds/tadtests/tmp/srl_enc.srl", "wb"); + FILE *srlFile = fopen("sd:/_nds/tadtests/tmp/temp.srl.enc", "wb"); fseek(file, tad.srlOffset, SEEK_SET); for (int i = 0; i < swap_endian_u32(header.srlSize); i++) { char ch = fgetc(file); @@ -209,7 +212,7 @@ int decryptTad(char const* src) iprintf("Decrypting SRL:\n\n"); iprintf(" Finding title key...\n"); - FILE *ticket = fopen("sd:/_nds/tadtests/tmp/ticket.srl", "rb"); + FILE *ticket = fopen("sd:/_nds/tadtests/tmp/temp.tik", "rb"); unsigned char title_key_enc[16]; fseek(ticket, 447, SEEK_SET); fread(title_key_enc, 1, 16, ticket); @@ -251,19 +254,22 @@ int decryptTad(char const* src) iprintf("\n Decrypting SRL chunks...\n"); unsigned char srl_buffer_enc[16]; unsigned char srl_buffer_dec[16]; + // Should be fine as a hardcoded string. Content IV is based off of the content index. (index # with zerobyte padding) + // All TADs I've only ever a single content. It might be a good idea to add something down the line in case a weird + // TAD pops up, but until then this should do. unsigned char content_iv[] = { 0x00, 0x00, 0x00, 0x00 ,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - FILE *srlFile_enc = fopen("sd:/_nds/tadtests/tmp/srl_enc.srl", "rb"); + FILE *srlFile_enc = fopen("sd:/_nds/tadtests/tmp/temp.srl.enc", "rb"); fseek(srlFile_enc, 0, SEEK_SET); - FILE *srlFile_dec = fopen("sd:/_nds/tadtests/tmp/tad.srl", "wb"); + FILE *srlFile_dec = fopen("sd:/_nds/tadtests/tmp/temp.srl", "wb"); fseek(srlFile_dec, 0, SEEK_SET); for (int i = 0; i < swap_endian_u32(header.srlSize);) { fread(srl_buffer_enc, 1, 16, srlFile_enc); /* ===== silly debug ===== */ - iprintf("%ld - %d / %ld", ftell(file), i, swap_endian_u32(header.srlSize)); + iprintf("%ld - %d / %ld\n", ftell(file), i, swap_endian_u32(header.srlSize)); /* ===== end of debug ===== */ decrypt_cbc(title_key_dec, content_iv, srl_buffer_enc, 16, 16, srl_buffer_dec); @@ -272,9 +278,75 @@ int decryptTad(char const* src) } fclose(srlFile_enc); fclose(srlFile_dec); - iprintf("\nDone everything!"); + iprintf("\nReady to install!"); + return "sd:/_nds/tadtests/tmp/temp.srl"; +} - //return copyFilePart(src, 0, size, dst); - return 0; +void printTadInfo(char const* fpath) +{ + clearScreen(&topScreen); + if (!fpath) return; + + + uint32_t srlCompany; + uint32_t srlTidLow; + uint32_t srlTidHigh; + unsigned char srlVerLow = 0x00; + unsigned char srlVerHigh = 0x00; + + FILE *file = fopen(fpath, "rb"); + Header header; + fread(&header, sizeof(Header), 1, file); + iprintf("Parsing TAD header:\n"); + Tad tad; + tad.hdrOffset = 0; + // All offsets in the TAD are aligned to 64 bytes. + tad.certOffset = round_up(swap_endian_u32(header.hdrSize), 64); + tad.crlOffset = round_up(tad.certOffset + swap_endian_u32(header.certSize), 64); + tad.ticketOffset = round_up(tad.crlOffset + swap_endian_u32(header.crlSize), 64); + tad.tmdOffset = round_up(tad.ticketOffset + swap_endian_u32(header.ticketSize), 64); + tad.srlOffset = round_up(tad.tmdOffset + swap_endian_u32(header.tmdSize), 64); + tad.metaOffset = round_up(tad.srlOffset + swap_endian_u32(header.srlSize), 64); + // Get info from TMD. + fseek(file, swap_endian_u32(tad.tmdOffset)+396, SEEK_SET); + fread(srlTidHigh, 1, 4, file); + fread(srlTidLow, 1, 4, file); + fseek(file, swap_endian_u32(tad.tmdOffset)+408, SEEK_SET); + fread(srlCompany, 1, 4, file); + fseek(file, swap_endian_u32(tad.tmdOffset)+476, SEEK_SET); + fread(srlVerHigh, 1, 1, file); + fread(srlVerLow, 1, 1, file); + + iprintf(" tadVersion: %u\n", swap_endian_u16(header.tadVersion)); + iprintf(" certSize: %lu\n", swap_endian_u32(header.certSize)); + iprintf(" certOffset: %lu\n", tad.certOffset); + iprintf(" crlSize: %lu\n", swap_endian_u32(header.crlSize)); + iprintf(" crlOffset: %lu\n", tad.crlOffset); + iprintf(" ticketSize: %lu\n", swap_endian_u32(header.ticketSize)); + iprintf(" ticketOffset: %lu\n", tad.ticketOffset); + iprintf(" tmdSize: %lu\n", swap_endian_u32(header.tmdSize)); + iprintf(" tmdOffset: %lu\n", tad.tmdOffset); + iprintf(" srlSize: %lu\n", swap_endian_u32(header.srlSize)); + iprintf(" srlOffset: %lu\n", tad.srlOffset); + iprintf(" metaSize: %lu\n", swap_endian_u32(header.metaSize)); + iprintf(" metaOffset: %lu\n", tad.metaOffset); + + //proper title + // TODO! Might not be possible though :(( + + //size in blocks, rounded up + iprintf("Size: (%ld blocks)\n", ((swap_endian_u32(header.srlSize) / BYTES_PER_BLOCK) * BYTES_PER_BLOCK + BYTES_PER_BLOCK) / BYTES_PER_BLOCK); + + iprintf("Game Code: %c\n", (char)srlTidLow); + + iprintf("Game Version: %u.%u (NUS: v%u)\n", srlVerHigh * 256, srlVerLow, (srlVerHigh * 256) + srlVerLow); + + iprintf("Company Code: %c (%lu)\n", (char)srlCompany, srlCompany); + + // Print program type based on TID high? + iprintf("Title ID: %08lx %08lx", srlTidHigh, srlTidLow); + + //print full file path + iprintf("\n%s\n", fpath); } \ No newline at end of file diff --git a/arm9/src/titlemenu.c b/arm9/src/titlemenu.c index cb8d18d..1795bde 100644 --- a/arm9/src/titlemenu.c +++ b/arm9/src/titlemenu.c @@ -92,6 +92,7 @@ static void generateList(Menu* m) const char* dirs[] = { "00030004", "00030005", + //"0003000f", "00030015", "00030017" }; @@ -100,17 +101,12 @@ static void generateList(Menu* m) { // 00030004 NULL //nothing blacklisted }, - { // 00030005 - "484e44", // DS Download Play - "484e45", // PictoChat - "484e49", // Nintendo DSi Camera - "484e4a", // Nintendo Zone - "484e4b", // Nintendo DSi Sound + { // 0003000f + "484e43", // WiFi Firmware NULL }, { // 00030015 "484e42", // System Settings - "484e46", // Nintendo DSi Shop NULL }, { // 00030017 @@ -159,8 +155,7 @@ static void generateList(Menu* m) blacklisted = true; // also blacklist specific all-region titles - if ((strcmp("484e4441", ent->d_name) == 0) || // Download Play - (strcmp("484e4541", ent->d_name) == 0) || // PictoChat + if ((strcmp("484e4341", ent->d_name) == 0) || // WiFi Firmware (strcmp("34544e41", ent->d_name) == 0)) // TwlNmenu blacklisted = true; } diff --git a/icon.bmp b/icon.bmp index eba498d..fbdaba4 100644 Binary files a/icon.bmp and b/icon.bmp differ diff --git a/icon.gif b/icon.gif new file mode 100644 index 0000000..548f48e Binary files /dev/null and b/icon.gif differ