From faabd8305d5e245956f67fbd8452e21747aa8d3f Mon Sep 17 00:00:00 2001 From: Tim Seidel Date: Thu, 18 Mar 2021 10:36:08 +0100 Subject: [PATCH 1/5] - fixed string encoings and default values (Resulted in unreadable name and icon) in final nds. --- fix_ndsheader.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/fix_ndsheader.py b/fix_ndsheader.py index 38ee936..9e1f77d 100644 --- a/fix_ndsheader.py +++ b/fix_ndsheader.py @@ -46,7 +46,10 @@ def getBytes(e): if (sys.version_info.major == 2): return bytes(e) else: - return bytes(e, "utf-8") + try: + return e.encode('ascii') + except: + print("ERROR: " + e) ; # # CRC16 MODULE # @@ -113,7 +116,7 @@ def skipUntilAddress(f_in,f_out, caddr, taddr): f_out.write(chunk) def writeBlankuntilAddress(f_out, caddr, taddr): - f_out.write(getBytes("\x00"*(taddr-caddr))) + f_out.write(bytes([0])*(taddr-caddr)) fname=args.file @@ -400,21 +403,21 @@ else: # Fix srlSignedHeader if not args.read: srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= '\xff'*20, - arm9WithSecAreaSha1Hmac= '\xff'*20, - bannerSha1Hmac= '\xff'*20, - signature= '\xff'*128 + arm7Sha1Hmac= bytes([255])*20, + arm9WithSecAreaSha1Hmac= bytes([255])*20, + bannerSha1Hmac= bytes([255])*20, + signature= bytes([255])*128 ) if "dsi" in args.mode : srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= '\xff'*20, - arm7iSha1Hmac= '\xff'*20, - arm9Sha1Hmac= '\xff'*20, - arm9WithSecAreaSha1Hmac= '\xff'*20, - arm9iSha1Hmac= '\xff'*20, - bannerSha1Hmac= '\xff'*20, - digestMasterSha1Hmac= '\xff'*20, - signature= '\xff'*128 + arm7Sha1Hmac= bytes([255])*20, + arm7iSha1Hmac= bytes([255])*20, + arm9Sha1Hmac= bytes([255])*20, + arm9WithSecAreaSha1Hmac= bytes([255])*20, + arm9iSha1Hmac= bytes([255])*20, + bannerSha1Hmac= bytes([255])*20, + digestMasterSha1Hmac= bytes([255])*20, + signature= bytes([255])*128 ) if args.verbose or args.read: pprint(dict(srlSignedHeader._asdict())) @@ -479,7 +482,7 @@ if not args.read: filew.write(data1) filew.write(data2) filew.write(data3[0:0xC80]) - filew.write(getBytes('\xff'*16*8)) + filew.write(bytes([255])*16*8) writeBlankuntilAddress(filew,0x1000,0x4000) if arm9Footer.nitrocode != 0xDEC00621: From 9e00e5394e6965e01624df1aa92c5c2855d68928 Mon Sep 17 00:00:00 2001 From: urmum-69 Date: Sat, 20 Mar 2021 18:54:21 +0000 Subject: [PATCH 2/5] Implement calculating SHA1 hash of files (#86) * implement calculating SHA1 hash of a file * fix bug where incorrect SHA1 hash would be calculated --- arm9/source/fileOperations.cpp | 34 ++++++++++++++++++++++++++++++++++ arm9/source/fileOperations.h | 1 + arm9/source/file_browse.cpp | 31 +++++++++++++++++++++++++++++-- arm9/source/file_browse.h | 1 + 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/arm9/source/fileOperations.cpp b/arm9/source/fileOperations.cpp index 14e1d81..5c1b33e 100644 --- a/arm9/source/fileOperations.cpp +++ b/arm9/source/fileOperations.cpp @@ -9,6 +9,7 @@ #include "file_browse.h" #define copyBufSize 0x8000 +#define shaChunkSize 0x10000 u32 copyBuf[copyBufSize]; @@ -68,6 +69,39 @@ off_t getFileSize(const char *fileName) return fsize; } +bool calculateSHA1(const char *fileName, u8 *sha1) +{ + off_t fsize = getFileSize(fileName); + u8 *buf = (u8*) malloc(shaChunkSize); + if (!buf) { + iprintf("Could not allocate buffer\n"); + return false; + } + FILE* fp = fopen(fileName, "rb"); + if (!fp) { + iprintf("Could not open file for reading\n"); + free(buf); + return false; + } + memset(sha1, 0, 20); + swiSHA1context_t ctx; + ctx.sha_block=0; //this is weird but it has to be done + swiSHA1Init(&ctx); + while (true) { + size_t ret = fread(buf, 1, shaChunkSize, fp); + if (!ret) break; + swiSHA1Update(&ctx, buf, ret); + scanKeys(); + int keys = keysHeld(); + if (keys & KEY_START) return false; + iprintf("\x1b[1;A"); + iprintf("%ld/%lld bytes\n", ftell(fp), fsize); + } + swiSHA1Final(sha1, &ctx); + free(buf); + return true; +} + void dirCopy(DirEntry* entry, int i, const char *destinationPath, const char *sourcePath) { std::vector dirContents; dirContents.clear(); diff --git a/arm9/source/fileOperations.h b/arm9/source/fileOperations.h index 795ebed..a7e0931 100644 --- a/arm9/source/fileOperations.h +++ b/arm9/source/fileOperations.h @@ -23,6 +23,7 @@ extern void printBytes(int bytes); extern void printBytesAlign(int bytes); extern off_t getFileSize(const char *fileName); +extern bool calculateSHA1(const char *fileName, u8 *sha1); extern int fcopy(const char *sourcePath, const char *destinationPath); void changeFileAttribs(DirEntry* entry); diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index 052fa6a..fc73e01 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -242,8 +242,12 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { assignedOp[++maxCursors] = FileOperation::copyFatOut; printf(" Copy to fat:/gm9i/out\n"); } - printf("\n"); - printf("( select, cancel)"); + // The bios SHA1 functions are only availible on the DSi + // https://problemkaputt.de/gbatek.htm#biossha1functionsdsionly + if (isDSiMode()) { + assignedOp[++maxCursors] = FileOperation::calculateSHA1; + printf(" Calculate SHA1 hash\n"); + } consoleSelect(&bottomConsole); printf ("\x1B[47m"); // Print foreground white color while (true) { @@ -375,6 +379,29 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { currentDrive = 6; } break; + } case FileOperation::calculateSHA1: { + iprintf("\x1b[2J"); + iprintf("Calculating SHA1 hash of:\n%s\n", entry->name.c_str()); + iprintf("Press to cancel\n\n"); + u8 sha1[20] = {0}; + bool ret = calculateSHA1(strcat(getcwd(path, PATH_MAX), entry->name.c_str()), sha1); + if (!ret) break; + iprintf("SHA1 hash is: "); + for (int i = 0; i < 19; ++i) iprintf("%02X", sha1[i]); + consoleSelect(&topConsole); + iprintf ("\x1B[30m"); // Print black color + // Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do + int pressed; + do { + // Move to right side of screen + iprintf ("\x1b[0;26H"); + // Print time + iprintf (" %s" ,RetTime().c_str()); + scanKeys(); + pressed = keysDownRepeat(); + swiWaitForVBlank(); + } while (!(pressed & (KEY_A | KEY_Y | KEY_B | KEY_X))); + break; } case FileOperation::none: { break; } diff --git a/arm9/source/file_browse.h b/arm9/source/file_browse.h index 0255590..367543e 100644 --- a/arm9/source/file_browse.h +++ b/arm9/source/file_browse.h @@ -43,6 +43,7 @@ enum class FileOperation { showInfo, copySdOut, copyFatOut, + calculateSHA1, }; bool extension(const std::string &filename, const std::vector &extensions); From 4c726266f79f9a1365ba62b70498117a2157bd31 Mon Sep 17 00:00:00 2001 From: urmum-69 Date: Thu, 25 Mar 2021 00:02:54 +0000 Subject: [PATCH 3/5] don't run b4ds anymore, as it is obsolete (#87) * don't run b4ds anymore, as it is obsolete * fix off by one error when printing SHA1 hash --- arm9/source/fileOperations.cpp | 2 +- arm9/source/file_browse.cpp | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/arm9/source/fileOperations.cpp b/arm9/source/fileOperations.cpp index 5c1b33e..c8777bb 100644 --- a/arm9/source/fileOperations.cpp +++ b/arm9/source/fileOperations.cpp @@ -95,7 +95,7 @@ bool calculateSHA1(const char *fileName, u8 *sha1) int keys = keysHeld(); if (keys & KEY_START) return false; iprintf("\x1b[1;A"); - iprintf("%ld/%lld bytes\n", ftell(fp), fsize); + iprintf("%ld/%lld bytes processed\n", ftell(fp), fsize); } swiSHA1Final(sha1, &ctx); free(buf); diff --git a/arm9/source/file_browse.cpp b/arm9/source/file_browse.cpp index fc73e01..0d83931 100644 --- a/arm9/source/file_browse.cpp +++ b/arm9/source/file_browse.cpp @@ -242,12 +242,13 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { assignedOp[++maxCursors] = FileOperation::copyFatOut; printf(" Copy to fat:/gm9i/out\n"); } - // The bios SHA1 functions are only availible on the DSi + // The bios SHA1 functions are only available on the DSi // https://problemkaputt.de/gbatek.htm#biossha1functionsdsionly if (isDSiMode()) { assignedOp[++maxCursors] = FileOperation::calculateSHA1; printf(" Calculate SHA1 hash\n"); } + printf("\n( select, cancel)"); consoleSelect(&bottomConsole); printf ("\x1B[47m"); // Print foreground white color while (true) { @@ -307,7 +308,7 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { // TODO Something less hacky lol chdir(isDSiMode()&&sdMounted ? "sd:/_nds" : "fat:/_nds"); // TODO Read header and check for homebrew flag, based on that runNdsFile nds-bootstrap(-hb)-release - entry->name = isDSiMode() ? "nds-bootstrap-release.nds" : "b4ds-release.nds"; + entry->name = "nds-bootstrap-release.nds"; applaunch = true; return FileOperation::bootFile; break; @@ -386,8 +387,8 @@ FileOperation fileBrowse_A(DirEntry* entry, char path[PATH_MAX]) { u8 sha1[20] = {0}; bool ret = calculateSHA1(strcat(getcwd(path, PATH_MAX), entry->name.c_str()), sha1); if (!ret) break; - iprintf("SHA1 hash is: "); - for (int i = 0; i < 19; ++i) iprintf("%02X", sha1[i]); + iprintf("SHA1 hash is: \n"); + for (int i = 0; i < 20; ++i) iprintf("%02X", sha1[i]); consoleSelect(&topConsole); iprintf ("\x1B[30m"); // Print black color // Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do From 7463102ce0fda37673a2ff8bc28b39f9f7e5622c Mon Sep 17 00:00:00 2001 From: Pk11 Date: Thu, 25 Mar 2021 17:10:21 -0500 Subject: [PATCH 4/5] Fix 128KiB EEPROM save dumping (#88) --- arm9/source/dumpOperations.cpp | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/arm9/source/dumpOperations.cpp b/arm9/source/dumpOperations.cpp index e37f0a1..80358d4 100644 --- a/arm9/source/dumpOperations.cpp +++ b/arm9/source/dumpOperations.cpp @@ -20,13 +20,29 @@ extern PrintConsole topConsole, bottomConsole; static sNDSHeaderExt ndsCardHeader; +//--------------------------------------------------------------------------------- +// https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L74 +// with Pokémon Mystery Dungeon - Explorers of Sky (128 KiB EEPROM) fixed +int cardEepromGetTypeFixed(void) { +//--------------------------------------------------------------------------------- + int sr = cardEepromCommand(SPI_EEPROM_RDSR); + int id = cardEepromReadID(); + + if (( sr == 0xff && id == 0xffffff) || ( sr == 0 && id == 0 )) return -1; + if ( sr == 0xf0 && id == 0xffffff ) return 1; + if ( sr == 0x00 && id == 0xffffff ) return 2; + if ( id != 0xffffff || ( sr == 0x02 && id == 0xffffff )) return 3; + + return 0; +} + //--------------------------------------------------------------------------------- // https://github.com/devkitPro/libnds/blob/master/source/common/cardEeprom.c#L88 // with type 2 fixed if the first word and another % 8192 location are 0x00000000 uint32 cardEepromGetSizeFixed() { //--------------------------------------------------------------------------------- - int type = cardEepromGetType(); + int type = cardEepromGetTypeFixed(); if(type == -1) return 0; @@ -92,6 +108,13 @@ uint32 cardEepromGetSizeFixed() { if (device == 0x2211) return 128*1024; // 1Mbit(128KByte) - MX25L1021E } + + if (id == 0xffffff) { + int sr = cardEepromCommand(SPI_EEPROM_RDSR); + if (sr == 2) { // Pokémon Mystery Dungeon - Explorers of Sky + return 128*1024; // 1Mbit (128KByte) + } + } return 256*1024; // 2Mbit(256KByte) @@ -121,7 +144,7 @@ void ndsCardSaveDump(const char* filename) { auxspi_read_data(0, buffer, LEN*size_blocks, type, card_type); fwrite(buffer, 1, LEN*size_blocks, out); } else { - int type = cardEepromGetType(); + int type = cardEepromGetTypeFixed(); int size = cardEepromGetSizeFixed(); buffer = new unsigned char[size]; cardReadEeprom(0, buffer, size, type); @@ -187,7 +210,7 @@ void ndsCardSaveRestore(const char *filename) { LEN = 1 << shift; num_blocks = 1 << (size - shift); } else { - type = cardEepromGetType(); + type = cardEepromGetTypeFixed(); size = cardEepromGetSizeFixed(); } fseek(in, 0, SEEK_END); @@ -315,7 +338,7 @@ void ndsCardDump(void) { char gameCode[7] = {0}; tonccpy(gameCode, ndsCardHeader.gameCode, 6); char destSavPath[256]; - sprintf(destSavPath, "%s:/gm9i/out/%s_%s_%x.sav", (sdMounted ? "sd" : "fat"), gameTitle, gameCode, ndsCardHeader.romversion); + sprintf(destSavPath, "%s:/gm9i/out/%s_%s_%02x.sav", (sdMounted ? "sd" : "fat"), gameTitle, gameCode, ndsCardHeader.romversion); ndsCardSaveDump(destSavPath); } else if ((pressed & KEY_A) || (pressed & KEY_Y)) { @@ -386,7 +409,7 @@ void ndsCardDump(void) { if (gameCode[0] == 0 || gameCode[0] == 0x23 || gameCode[0] == 0xFF) { sprintf(gameCode, "NONE00"); } - sprintf(fileName, "%s_%s_%x%s", gameTitle, gameCode, ndsCardHeader.romversion, (trimRom ? "_trim" : "")); + sprintf(fileName, "%s_%s_%02x%s", gameTitle, gameCode, ndsCardHeader.romversion, (trimRom ? "_trim" : "")); sprintf(destPath, "%s:/gm9i/out/%s.nds", (sdMounted ? "sd" : "fat"), fileName); sprintf(destSavPath, "%s:/gm9i/out/%s.sav", (sdMounted ? "sd" : "fat"), fileName); From fb7371de4afa02176e068c3596e9be626a1cd9a0 Mon Sep 17 00:00:00 2001 From: Pk11 Date: Thu, 25 Mar 2021 17:42:28 -0500 Subject: [PATCH 5/5] Fix fix_ndsheader.py being broken in Python 2 (#89) --- fix_ndsheader.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/fix_ndsheader.py b/fix_ndsheader.py index 9e1f77d..1676adc 100644 --- a/fix_ndsheader.py +++ b/fix_ndsheader.py @@ -49,7 +49,7 @@ def getBytes(e): try: return e.encode('ascii') except: - print("ERROR: " + e) ; + print("ERROR: {}".format(e)) # # CRC16 MODULE # @@ -116,7 +116,7 @@ def skipUntilAddress(f_in,f_out, caddr, taddr): f_out.write(chunk) def writeBlankuntilAddress(f_out, caddr, taddr): - f_out.write(bytes([0])*(taddr-caddr)) + f_out.write(b"\x00"*(taddr-caddr)) fname=args.file @@ -403,21 +403,21 @@ else: # Fix srlSignedHeader if not args.read: srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= bytes([255])*20, - arm9WithSecAreaSha1Hmac= bytes([255])*20, - bannerSha1Hmac= bytes([255])*20, - signature= bytes([255])*128 + arm7Sha1Hmac= b'\xff'*20, + arm9WithSecAreaSha1Hmac= b'\xff'*20, + bannerSha1Hmac= b'\xff'*20, + signature= b'\xff'*128 ) if "dsi" in args.mode : srlSignedHeader=srlSignedHeader._replace( - arm7Sha1Hmac= bytes([255])*20, - arm7iSha1Hmac= bytes([255])*20, - arm9Sha1Hmac= bytes([255])*20, - arm9WithSecAreaSha1Hmac= bytes([255])*20, - arm9iSha1Hmac= bytes([255])*20, - bannerSha1Hmac= bytes([255])*20, - digestMasterSha1Hmac= bytes([255])*20, - signature= bytes([255])*128 + arm7Sha1Hmac= b'\xff'*20, + arm7iSha1Hmac= b'\xff'*20, + arm9Sha1Hmac= b'\xff'*20, + arm9WithSecAreaSha1Hmac= b'\xff'*20, + arm9iSha1Hmac= b'\xff'*20, + bannerSha1Hmac= b'\xff'*20, + digestMasterSha1Hmac= b'\xff'*20, + signature= b'\xff'*128 ) if args.verbose or args.read: pprint(dict(srlSignedHeader._asdict())) @@ -482,7 +482,7 @@ if not args.read: filew.write(data1) filew.write(data2) filew.write(data3[0:0xC80]) - filew.write(bytes([255])*16*8) + filew.write(b'\xff'*16*8) writeBlankuntilAddress(filew,0x1000,0x4000) if arm9Footer.nitrocode != 0xDEC00621: