From 2aa63f9ada589e262f4e9827b1a4389a75d3a756 Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Sun, 13 Aug 2017 20:01:04 +0900 Subject: [PATCH 1/8] Removed all unused comments --- extract_orig_header.py | 2 + source/ak2i.c | 91 ------------------------------------------ 2 files changed, 2 insertions(+), 91 deletions(-) diff --git a/extract_orig_header.py b/extract_orig_header.py index 4ef4593..debb3d9 100644 --- a/extract_orig_header.py +++ b/extract_orig_header.py @@ -2,6 +2,8 @@ with open(sys.argv[1], 'rb') as r: d = r.read()[0x2000:0x3000] + with open(sys.argv[1] + '.nds', 'wb') as w: + w.write(d) print 'uint8_t orig_header[] = {' for idx, x in enumerate(d): diff --git a/source/ak2i.c b/source/ak2i.c index 0884690..68a43a1 100644 --- a/source/ak2i.c +++ b/source/ak2i.c @@ -328,91 +328,16 @@ void flash(u16 hwid) { void readFirm(u32 *dest) { } -/* -void getHttp(char* url) { -//--------------------------------------------------------------------------------- - // Let's send a simple HTTP request to a server and print the results! - - // store the HTTP request for later - const char * request_text = - "GET /dswifi/example1.php HTTP/1.1\r\n" - "Host: www.akkit.org\r\n" - "User-Agent: Nintendo DS\r\n\r\n"; - - // Find the IP address of the server, with gethostbyname - struct hostent * myhost = gethostbyname( url ); - iprintf("Found IP Address!\n"); - - // Create a TCP socket - int my_socket; - my_socket = socket( AF_INET, SOCK_STREAM, 0 ); - iprintf("Created Socket!\n"); - - // Tell the socket to connect to the IP address we found, on port 80 (HTTP) - struct sockaddr_in sain; - sain.sin_family = AF_INET; - sain.sin_port = htons(80); - sain.sin_addr.s_addr= *( (unsigned long *)(myhost->h_addr_list[0]) ); - connect( my_socket,(struct sockaddr *)&sain, sizeof(sain) ); - iprintf("Connected to server!\n"); - - // send our request - send( my_socket, request_text, strlen(request_text), 0 ); - iprintf("Sent our request!\n"); - - // Print incoming data - iprintf("Printing incoming data:\n"); - - int recvd_len; - char incoming_buffer[256]; - - while( ( recvd_len = recv( my_socket, incoming_buffer, 255, 0 ) ) != 0 ) { // if recv returns 0, the socket has been closed. - if(recvd_len>0) { // data was received! - incoming_buffer[recvd_len] = 0; // null-terminate - iprintf(incoming_buffer); - } - } - - iprintf("Other side closed connection!"); - - shutdown(my_socket,0); // good practice to shutdown the socket. - - closesocket(my_socket); // remove the socket. -} -*/ void dump(u16 hwid) { char *fn; -// chdir("sd:/"); -// -// switch (hwid) { -// case 0x8181: -// fn = "/firm8181.bin"; -// break; -// case 0x4444: -// fn = "/firm4444.bin"; -// break; -// default: -// // return; -// fn = "/firm0000.bin"; -// break; -// } -// iprintf("open file: %s\n", fn); -// FILE* outf = fopen(fn, "wb"); -// if (outf == NULL) { -// iprintf("Cannot open file\n"); -// return; -// } iprintf("Start dump, DO NOT turn off DS.\n"); iprintf("0%%"); - //fwrite("START", 1, 5, outf); u32 offset = 0; - //u32 pos = 0; u32 data; u32 prog = 0; do { -// iprintf("+ send command\n"); u8 command[8] = {0, 0, 0, 0, offset & 0xff, offset >> 8 & 0xff, offset >> 16 & 0xff, CARD_CMD_HEADER_READ}; @@ -420,29 +345,13 @@ void dump(u16 hwid) { command[5] = offset >> 8 & 0xff; command[4] = offset & 0xff; ak2iCardWriteAndRead(command, 4, 0, &data); -// iprintf(" - command end\n"); - //dest[pos] = data; offset += 4; - //pos += 1; u32 cur = getProgress(offset, 0, 0x20000); if (cur != prog && (cur % 5) == 0) { -// iprintf("..%lu%%", cur); prog = cur; } -// fwrite(&data, 4, 1, outf); iprintf("%lx", data); } while (offset != 0x20000); printf("\n"); - //for (u32 addr = 0x80000; addr < 0x1ce000; addr += 1) { - // u32 cur = getProgress(addr, 0x80000, 0x1ce000); - // if (cur != prog && (cur % 5) == 0) { - // iprintf("..%lu%%", cur); - // prog = cur; - // } - // u8* data = (u8*)addr; - // fwrite(data, 1, 1, outf); - //} - //fwrite("END", 1, 3, outf); -// fclose(outf); iprintf("\nDone\n"); } From 2f5ae5607b4ceddeb3162c6a6dd69bc4f53483cf Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Sun, 13 Aug 2017 20:14:15 +0900 Subject: [PATCH 2/8] Add .vimrc --- .vimrc | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .vimrc diff --git a/.vimrc b/.vimrc new file mode 100644 index 0000000..853cf19 --- /dev/null +++ b/.vimrc @@ -0,0 +1,5 @@ +let g:syntastic_cpp_compiler = $DEVKITARM.'/bin/arm-none-eabi-g++' +let g:syntastic_cpp_compiler_options = "-DARM9" +let g:syntastic_cpp_include_dirs = [".", "include", $DEVKITPRO."/libnds/include"] +set colorcolumn=80 + From 1bc9402dfd4f52045e84d086c7dffad739ff9722 Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Sun, 13 Aug 2017 22:55:27 +0900 Subject: [PATCH 3/8] Add ntrboothax feature not tested yet --- .gitmodules | 3 + .vimrc | 2 +- Makefile | 4 +- binaries/EMPTY | 0 external/flashcart_core | 1 + extract_binaries.py | 35 +++ extract_orig_header.py | 14 - include/DrawCharacter.h | 7 + include/delay.h | 6 + include/gamecart/protocol.h | 0 include/gamecart/protocol_ntr.h | 5 + source/ak2i.c | 357 ------------------------- source/gamecart.cpp | 41 +++ source/main.cpp | 443 ++++++-------------------------- 14 files changed, 181 insertions(+), 737 deletions(-) create mode 100644 .gitmodules create mode 100644 binaries/EMPTY create mode 160000 external/flashcart_core create mode 100644 extract_binaries.py delete mode 100644 extract_orig_header.py create mode 100644 include/DrawCharacter.h create mode 100644 include/delay.h create mode 100644 include/gamecart/protocol.h create mode 100644 include/gamecart/protocol_ntr.h delete mode 100644 source/ak2i.c create mode 100644 source/gamecart.cpp diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..d2c158d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "external/flashcart_core"] + path = external/flashcart_core + url = https://github.com/kitling/flashcart_core diff --git a/.vimrc b/.vimrc index 853cf19..80f2792 100644 --- a/.vimrc +++ b/.vimrc @@ -1,5 +1,5 @@ let g:syntastic_cpp_compiler = $DEVKITARM.'/bin/arm-none-eabi-g++' let g:syntastic_cpp_compiler_options = "-DARM9" -let g:syntastic_cpp_include_dirs = [".", "include", $DEVKITPRO."/libnds/include"] +let g:syntastic_cpp_include_dirs = [".", "include", "external", $DEVKITPRO."/libnds/include"] set colorcolumn=80 diff --git a/Makefile b/Makefile index 7f98baa..45195dd 100644 --- a/Makefile +++ b/Makefile @@ -17,9 +17,9 @@ include $(DEVKITARM)/ds_rules #--------------------------------------------------------------------------------- TARGET := $(shell basename $(CURDIR)) BUILD := build -SOURCES := source +SOURCES := source external/flashcart_core DATA := data -INCLUDES := include +INCLUDES := include external #--------------------------------------------------------------------------------- # options for code generation diff --git a/binaries/EMPTY b/binaries/EMPTY new file mode 100644 index 0000000..e69de29 diff --git a/external/flashcart_core b/external/flashcart_core new file mode 160000 index 0000000..ad5d125 --- /dev/null +++ b/external/flashcart_core @@ -0,0 +1 @@ +Subproject commit ad5d125abd62c5effd9908f8dea8aa2aec65a45c diff --git a/extract_binaries.py b/extract_binaries.py new file mode 100644 index 0000000..2e07945 --- /dev/null +++ b/extract_binaries.py @@ -0,0 +1,35 @@ +import os.path +import glob + +strings = [ + '#ifndef BINARIES_H\n', + '#define BINARIES_H\n', + '#ifdef __cplusplus\n', + 'extern "C" {\n', + '#endif\n', +] + +for fn in glob.glob('binaries/*'): + basename = os.path.basename(fn) + var_name = basename.replace('.', '_') + with open(fn, 'rb') as r: + strings.append('uint8_t %s[] = {\n' % var_name); + buf = r.read() + + for idx, x in enumerate(buf): + strings.append('0x%02X, ' % ord(x)) + if (idx and ((idx + 1) % 16) == 0): + strings.append('\n') + strings.append('};\n'); + strings.append('uint32_t %s_size = 0x%X;\n' % (var_name, len(buf))) + +strings += [ + '#ifdef __cplusplus\n', + '}\n', + '#endif\n', + '#endif\n', +] + +with open('include/binaries.h', 'wb') as w: + w.write(''.join(strings)) + diff --git a/extract_orig_header.py b/extract_orig_header.py deleted file mode 100644 index debb3d9..0000000 --- a/extract_orig_header.py +++ /dev/null @@ -1,14 +0,0 @@ -import sys - -with open(sys.argv[1], 'rb') as r: - d = r.read()[0x2000:0x3000] - with open(sys.argv[1] + '.nds', 'wb') as w: - w.write(d) - - print 'uint8_t orig_header[] = {' - for idx, x in enumerate(d): - print ('0x%02X,' % ord(x)), - if (idx and ((idx + 1) % 16) == 0): - print - print '};' - diff --git a/include/DrawCharacter.h b/include/DrawCharacter.h new file mode 100644 index 0000000..c7da5e5 --- /dev/null +++ b/include/DrawCharacter.h @@ -0,0 +1,7 @@ +#ifndef DISPLAY_H +#define DISPLAY_H +#define TOP_SCREEN 0 + +void ShowProgress(char screen, uint32_t curr, uint32_t total); + +#endif diff --git a/include/delay.h b/include/delay.h new file mode 100644 index 0000000..a702539 --- /dev/null +++ b/include/delay.h @@ -0,0 +1,6 @@ +#ifndef DELAY_H +#define DELAY_H + +#define ioDelay(...) while(0) + +#endif diff --git a/include/gamecart/protocol.h b/include/gamecart/protocol.h new file mode 100644 index 0000000..e69de29 diff --git a/include/gamecart/protocol_ntr.h b/include/gamecart/protocol_ntr.h new file mode 100644 index 0000000..24993fb --- /dev/null +++ b/include/gamecart/protocol_ntr.h @@ -0,0 +1,5 @@ +#ifndef PROTOCOL_NTR_H +#define PROTOCOL_NTR_H +void Cart_NTRInit(); +void NTR_SendCommand(const uint8_t *command, uint32_t length, uint32_t flags, uint8_t *destination); +#endif diff --git a/source/ak2i.c b/source/ak2i.c deleted file mode 100644 index 68a43a1..0000000 --- a/source/ak2i.c +++ /dev/null @@ -1,357 +0,0 @@ -#include -#include -#include "ak2i.h" - -void ak2iCardWriteAndRead(const u8 *command, u32 length, u32 flags, - u32 *destination) { - cardWriteCommand(command); - u32 defaultFlags; - switch (length & 0xfffffffc) { - case 0: - defaultFlags = 0; - break; - case 4: - defaultFlags = CARD_BLK_SIZE(7); - break; - case 512: - defaultFlags = CARD_BLK_SIZE(1); - break; - case 8192: - defaultFlags = CARD_BLK_SIZE(5); - break; - case 16384: - defaultFlags = CARD_BLK_SIZE(6); - break; - default: - defaultFlags = CARD_BLK_SIZE(4); - break; - } - // NDSL only - cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET, - destination, length, command); - // NDSL, DSLi, etc... - //cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET | - // CARD_SEC_CMD | CARD_SEC_EN | CARD_SEC_DAT, - // destination, length, command); - return; -} - -u32 getChipID() { - const u8 command[8] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, CARD_CMD_DATA_CHIPID}; - u32 ret = 0; - ak2iCardWriteAndRead(command, 4, 0, &ret); - return ret; -} - -u16 getHWID() { - const u8 command[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD1}; - u32 ret = 0; - ak2iCardWriteAndRead(command, 4, 0, &ret); - return (u16)ret & 0xFF; -} - -void setMapTableAddress(u32 tableName, u32 tableInRamAddress) { - tableName &= 0x0F; - u32 cmd[2] = {0xD0000000 | (tableInRamAddress >> 8), - ((tableInRamAddress & 0xFF) << 24) | ((u8)tableName << 16) }; - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, 0, 0, NULL); -} - -void setFlash1681_81() { - const u8 command[8] = {0x06, 0xC6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8}; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); -} - -void activeFatMap() { - const u8 command[8] = {0x00, 0x00, 0x00, 0xAA, 0x55, 0xAA, 0x55, 0xC2}; - ak2iCardWriteAndRead(command, 4, 0, NULL); -} - -void unlockFlash() { - const u8 command[8] = {0x00, 0x00, 0x00, 0x55, 0xAA, 0x55, 0xAA, 0xC2}; - ak2iCardWriteAndRead(command, 0, 0, NULL); -} - -void unlockASIC() { - const u8 command[8] = {0x00, 0x00, 0x00, 0xAA, 0x55, 0x55, 0xAA, 0xC2}; - ak2iCardWriteAndRead(command, 4, 0, NULL); -} - -void lockFlash(void) { - const u8 command[8] = {0x00, 0x00, 0x00, 0x55, 0x55, 0xAA, 0xAA, 0xC2}; - ak2iCardWriteAndRead(command, 0, 0, NULL); -} - -void readFlash(u32 address, u8 *buffer, u32 length) { - length &= ~(0x03); - u32 cmd[2] = { 0xB7000000 | (address >> 8), (address & 0xff) << 24 | 0x00100000 }; - - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, length, CARD_DELAY1(2), buffer); -} - -static void waitFlashBusy() { - u32 state = 0; - const u8 command[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0}; - do { - //ioAK2Delay( 16 * 10 ); - ak2iCardWriteAndRead(command, 4, CARD_DELAY1(4), &state); - state &= 1; - } while(state != 0); -} - -void eraseFlashBlock_44(u32 address) { - u32 cmd[2] = {0xD4000000 | (address & 0x001fffff), (u32)(1<<16)}; - - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, 0, 0, NULL); - waitFlashBusy(); -} - -void eraseFlashBlock_81(u32 address) { - u32 cmd[2] = {0xD4000000 | (address & 0x001fffff), (u32)((0x30<<24) | (0x80<<16) | (0<<8) | (0x35))}; - - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); - waitFlashBusy(); -} - -void writeFlashByte_44(u32 address, u8 data) { - u32 cmd[2] = {0xD4000000 | (address & 0x001fffff), (u32)((data<<24) | (3<<16))}; - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); - waitFlashBusy(); -} - -void writeFlash_44(u32 address, const void *data, u32 length) { - u8 * pbuffer = (u8 *)data; - for(u32 i = 0; i < length; ++i) { - writeFlashByte_44(address, *(pbuffer + i)); - address++; - } -} - -void writeFlashByte_81(u32 address, u8 data) { - u32 cmd[2] = { 0xD4000000 | (address & 0x001fffff), (u32)((data<<24) | (0xa0<<16) | (0<<8) | (0x63)) }; - const u8 command[8] = { - cmd[1] >> 0 & 0xFF, - cmd[1] >> 8 & 0xFF, - cmd[1] >> 16 & 0xFF, - cmd[1] >> 24 & 0xFF, - cmd[0] >> 0 & 0xFF, - cmd[0] >> 8 & 0xFF, - cmd[0] >> 16 & 0xFF, - cmd[0] >> 24 & 0xFF, - }; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); - waitFlashBusy(); -} - -void writeFlash_81(u32 address, const void *data, u32 length) { - u8 * pbuffer = (u8 *)data; - for (u32 i = 0; i < length; ++i) { - writeFlashByte_81(address, *(pbuffer + i)); - address++; - } -} - -bool verifyFlash(void *src, u32 dest, u32 length) { - u8 verifyBuffer[512]; - u8 * pSrc = (u8 *)src; - for (u32 i = 0; i < length; i += 512) { - u32 toRead = 512; - if (toRead > length - i) - toRead = length - i; - readFlash(dest + i, verifyBuffer, toRead); - - for (u32 j = 0; j < toRead; ++j) { - if(verifyBuffer[j] != *(pSrc + i + j)) - return false; - } - } - return true; -} - -void command_d0() { - const u8 command[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0}; - ak2iCardWriteAndRead(command, 0, 0, NULL); -} - -u32 command_c2(u8 cmd1, u8 cmd2, u32 length) { - u32 ret = 0; - const u8 command[8] = {0x00, 0x00, 0x00, cmd2, cmd1, 0x55, 0xaa, 0xc2}; - ak2iCardWriteAndRead(command, length, 0, &ret); - return ret; -} - -void command_c8() { - const u8 command[8] = {0x06, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8}; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); -} - -void command_d4(u32 addr, u8 data, u32 cmd) { - u8 command[8] = {cmd & 0xff, cmd >> 8 & 0xff, cmd >> 16 & 0xff, data, - addr & 0xff, addr >> 8 & 0xff, addr >> 16 & 0xff, 0xd4}; - ak2iCardWriteAndRead(command, 0, CARD_DELAY1(20), NULL); -} - -void command_c0() { - u32 ret = 0; - u8 command[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0}; - do { - ak2iCardWriteAndRead(command, 4, 0, &ret); - } while (ret & 1); -} - -u32 getProgress(u32 cur, u32 start, u32 end) { - return (cur - start) * 100 / (end - start); -} - -void flash_8181() { - // start update - command_c2(0xaa, 0x55, 0); - command_c2(0x55, 0xaa, 4); - command_c8(); - - // 0x2000324 - - for (u32 addr = 0x80000; addr < 0x1ce000; addr += 0x10000) { - command_d4(addr, 0x30, 0x800035); - command_c0(); - } - - // write - // TODO read from firm file - u8* newFirmPos = (u8*)0x2009ecc; - u32 prog = 0; - iprintf("0%%"); - for (u32 addr = 0x80000; addr < 0x1ce000; addr += 1, newFirmPos += 1) { - u32 cur = getProgress(addr, 0x80000, 0x1ce000); - if (cur != prog && (cur % 5) == 0) { - iprintf("..%lu%%", cur); - prog = cur; - } - command_d4(addr, *newFirmPos, 0xa000e3); - command_c0(); - } - iprintf("\nDone\n"); -} - -void flash_4444() { - // start update - command_c2(0xaa, 0x55, 0); - command_c8(); - - // 0x2000324 - - for (u32 addr = 0x80000; addr < 0x1ce000; addr += 0x10000) { - command_d4(addr, 1, 0); - command_c0(); - } - - // write - // TODO read from firm file - u8* newFirmPos = (u8*)0x2009ecc; - u32 prog = 0; - iprintf("0%%"); - for (u32 addr = 0x80000; addr < 0x1ce000; addr += 1, newFirmPos += 1) { - u32 cur = getProgress(addr, 0x80000, 0x1ce000); - if (cur != prog && (cur % 5) == 0) { - iprintf("..%lu%%", cur); - prog = cur; - } - command_d4(addr, *newFirmPos, 0x830000); - command_c0(); - } - iprintf("\nDone\n"); -} - -void flash(u16 hwid) { - command_d0(); - iprintf("Updating, DO NOT turn off DS.\n"); - switch (hwid) { - case 0x8181: - flash_8181(); - return; - case 0x4444: - flash_4444(); - return; - } -} - -void readFirm(u32 *dest) { -} - -void dump(u16 hwid) { - char *fn; - - iprintf("Start dump, DO NOT turn off DS.\n"); - iprintf("0%%"); - u32 offset = 0; - u32 data; - u32 prog = 0; - do { - u8 command[8] = {0, 0, 0, 0, - offset & 0xff, offset >> 8 & 0xff, offset >> 16 & 0xff, - CARD_CMD_HEADER_READ}; - command[6] = offset >> 16 & 0xff; - command[5] = offset >> 8 & 0xff; - command[4] = offset & 0xff; - ak2iCardWriteAndRead(command, 4, 0, &data); - offset += 4; - u32 cur = getProgress(offset, 0, 0x20000); - if (cur != prog && (cur % 5) == 0) { - prog = cur; - } - iprintf("%lx", data); - } while (offset != 0x20000); - printf("\n"); - iprintf("\nDone\n"); -} diff --git a/source/gamecart.cpp b/source/gamecart.cpp new file mode 100644 index 0000000..088cfd3 --- /dev/null +++ b/source/gamecart.cpp @@ -0,0 +1,41 @@ +#include +#include +#include +#include +#include "gamecart/protocol_ntr.h" + +void Cart_NTRInit() { +} + +void NTR_SendCommand(const u8 *command, u32 length, u32 flags, u8 *destination) { + cardWriteCommand(command); + u32 defaultFlags; + switch (length & 0xfffffffc) { + case 0: + defaultFlags = 0; + break; + case 4: + defaultFlags = CARD_BLK_SIZE(7); + break; + case 512: + defaultFlags = CARD_BLK_SIZE(1); + break; + case 8192: + defaultFlags = CARD_BLK_SIZE(5); + break; + case 16384: + defaultFlags = CARD_BLK_SIZE(6); + break; + default: + defaultFlags = CARD_BLK_SIZE(4); + break; + } + // NDSL only + cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET, + (u32*)destination, length, command); + // NDSL, DSLi, etc... + //cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET | + // CARD_SEC_CMD | CARD_SEC_EN | CARD_SEC_DAT, + // destination, length, command); + return; +} diff --git a/source/main.cpp b/source/main.cpp index 8073a14..893d4ca 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -5,23 +5,10 @@ #include #include -#include "ak2i.h" -#include "ak2i_flash.h" - -struct ntrcardhax_info { - int32_t version; - u32 ntrcard_header_addr; - u32 rtfs_cfg_addr; - u32 rtfs_handle_addr; -}; - -#define AK2I_PATCH_LENGTH 0x20000 -#define AK2I_PAYLOAD_OFFSET 0x2000 -#define AK2I_PAYLOAD_LENGTH 0x1000 +#include "flashcart_core/device.h" +#include "binaries.h" -static u8 bootrom[AK2I_PATCH_LENGTH]; -static u8 payload[AK2I_PAYLOAD_LENGTH]; -static int payloadLength = 0x1000; +u8 *orig_flashrom; static uint16_t crc16tab[] = { @@ -59,54 +46,7 @@ static uint16_t crc16tab[] = 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 }; -static struct ntrcardhax_info o_ak2i_ntrcardhax_infos[6] = { - { 17120, 0x80e18f4, 0x80e4c0c, 0x80ec190 }, - { 18182, 0x80e18f4, 0x80e4c0c, 0x80ec190 }, - { 19216, 0x80e18f4, 0x80e4c0c, 0x80ec190 }, - { 20262, 0x80e18f4, 0x80e4c0c, 0x80ec190 }, - { 21288, 0x80e1cb4, 0x80e4bcc, 0x80ec150 }, - { 22313, 0x80e1cb4, 0x80e4bcc, 0x80ec150 }, -}; - -static struct ntrcardhax_info n_ak2i_ntrcardhax_infos[6] = { - { 17120, 0x80e2b34, 0x80e5e4c, 0x80ed3d0 }, - { 18182, 0x80e1974, 0x80e4c8c, 0x80ec210 }, - { 19218, 0x80e1974, 0x80e4c8c, 0x80ec210 }, - { 20262, 0x80e1974, 0x80e4c8c, 0x80ec210 }, - { 21288, 0x80f9d34, 0x80fcc4c, 0x81041d0 }, - { 22313, 0x80f9d34, 0x80fcc4c, 0x81041d0 }, -}; - -// ldr sp,=0x22140000 -// -// ;Disable IRQ -// mrs r0, cpsr -// orr r0, #(1<<7) -// msr cpsr_c, r0 -// -// adr r0, kernelmode -// swi 0x7B -// -//kernelmode: -// mov r2, #0x22 -// msr CPSR_c, #0xDF -// ldr r3, =0x33333333 ;R/W -// mcr p15, 0, r3,c5,c0, 2 -// mov r2, #0xCC -// mcr p15, 0, r3,c5,c0, 3 -// ldr r0, =0x23F00000 -// bx r0 -static u8 loader_bin[0x44] = -{ - 0x30, 0xD0, 0x9F, 0xE5, 0x00, 0x00, 0x0F, 0xE1, 0x80, 0x00, 0x80, 0xE3, 0x00, 0xF0, 0x21, 0xE1, - 0x00, 0x00, 0x8F, 0xE2, 0x7B, 0x00, 0x00, 0xEF, 0x22, 0x20, 0xA0, 0xE3, 0xDF, 0xF0, 0x21, 0xE3, - 0x14, 0x30, 0x9F, 0xE5, 0x50, 0x3F, 0x05, 0xEE, 0xCC, 0x20, 0xA0, 0xE3, 0x70, 0x3F, 0x05, 0xEE, - 0x08, 0x00, 0x9F, 0xE5, 0x10, 0xFF, 0x2F, 0xE1, 0x00, 0x00, 0x14, 0x22, 0x33, 0x33, 0x33, 0x33, - 0x00, 0x00, 0xF0, 0x23, -}; - - -void pause() { +void waitPressA() { iprintf("press \n\n"); while(1) { scanKeys(); @@ -117,25 +57,35 @@ void pause() { scanKeys(); } -void waitCartReady() { - u32 chipid; - u32 hwid; - +Flashcart* waitCartReady() { + Flashcart *cart = NULL; do { iprintf("Please eject & reinsert cartridge.\n"); - pause(); + waitPressA(); + + iprintf("ChipID: %08X\n", Flashcart::getChipID()); + iprintf("HW Rev: %08X\n", Flashcart::getHardwareVersion()); - chipid = getChipID(); - hwid = getHWID(); + cart = Flashcart::detectCart(); + } while(!cart); - iprintf("CHIP: 0x%04X HW: %X\n", chipid, hwid); - } while (chipid != 0xFC2 || (hwid != 0x81 && hwid != 0x44)); + iprintf("Detected: %s", cart->getDescription()); + + return cart; } int percent(int c, int t) { return c * 100 / t; } +void ShowProgress(char screen, uint32_t curr, uint32_t total) { + if (curr * 100 % total) { + return; + } + + iprintf("\r%3d%%", curr * 100 / total); +} + uint16_t calcCrc(u8 *data, uint32_t length) { uint16_t crc = (uint16_t)~0; @@ -146,64 +96,38 @@ uint16_t calcCrc(u8 *data, uint32_t length) return crc; } -int dump() { - // recheck; - u32 chipid = getChipID(); - if (chipid != 0xFC2) { - iprintf("Cartridge is not AK2i\n"); - return -1; - } - u32 hwid = getHWID(); - if (hwid != 0x81 && hwid != 0x44) { - iprintf("Cartridge is not AK2i\n"); - return -1; - } - - setMapTableAddress(AK2I_MTN_NOR_OFFSET, 0); +u8* dump(Flashcart *cart) { + u32 length = cart->getMaxLength(); - // setup flash to 1681 - if (hwid == 0x81) { - iprintf("Setup flash to 1681\n"); - setFlash1681_81(); - } + if (orig_flashrom) { + iprintf("already loaded original rom\n"); + iprintf("if continue, you will lost this data\n"); + iprintf("and you can lost restore chance\n"); + iprintf("Y. continue\n"); + iprintf("A. exit\n"); - iprintf("Active FAT MAP\n"); - activeFatMap(); - - int old = 0; + while (true) { + scanKeys(); + u32 keys = keysDown(); - iprintf("0%%"); - for (u32 i = 0, offset = 0, read = 0; i < AK2I_PATCH_LENGTH; i += 512) { - int curr = percent(i, AK2I_PATCH_LENGTH); - if (curr != old && curr % 5 == 0) { - iprintf("\r%d%%", curr); - old = curr; - } - u32 toRead = 512; - if (toRead > AK2I_PATCH_LENGTH - i) { - toRead = AK2I_PATCH_LENGTH - i; + if (keys & KEY_A) { + return NULL; + } else if (keys & KEY_Y) { + break; + } + swiWaitForVBlank(); } - memset(bootrom + offset, 0, toRead); - readFlash(i, bootrom + offset, toRead); - offset += toRead; + free(orig_flashrom); } - iprintf("\r100%%\n"); - - iprintf("Done\n\n"); - -// for (u32 i = 0; i < AK2I_PATCH_LENGTH; i += 16) { -// printf("%05X:%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n", -// i, -// bootrom[i], bootrom[i + 1], bootrom[i + 2], bootrom[i + 3], -// bootrom[i + 4], bootrom[i + 5], bootrom[i + 6], bootrom[i + 7], -// bootrom[i + 8], bootrom[i + 9], bootrom[i + 10], bootrom[i + 11], -// bootrom[i + 12], bootrom[i + 13], bootrom[i + 14], bootrom[i + 15]); -// -// if (i % 10 == 0) { -// pause(); -// } -// } -// pause(); + + orig_flashrom = static_cast(malloc(sizeof(u8) * length)); + memset(orig_flashrom, 0, sizeof(u8) * length); + u8 *temp = orig_flashrom; + iprintf("\n"); + ShowProgress(0, 0, 1); + cart->readFlash(0, length, temp); + ShowProgress(0, 1, 1); + iprintf("\nDone\n\n"); return 0; } @@ -211,17 +135,17 @@ int dump() { int8_t selectDeviceType() { iprintf("Use arrow keys\nand to choose device type\n"); - u8 is_new = 0; + u8 is_dev = 0; while (true) { - iprintf("\r%s", is_new ? "NEW 3DS" : "OLD 3DS"); + iprintf("\r%s", is_dev ? "DEV" : "RETAIL"); scanKeys(); u32 keys = keysDown(); if (keys & (KEY_UP | KEY_DOWN)) { - is_new = (is_new + 1) & 1; + is_dev = (is_dev + 1) & 1; } else if (keys & KEY_A) { iprintf("\n\n"); - return is_new; + return is_dev; } else if (keys & KEY_B) { iprintf("\r(cancelled by user)\n\n"); return -1; @@ -230,259 +154,55 @@ int8_t selectDeviceType() { } } -int32_t selectFirmVersion(int8_t device) { - iprintf("Use arrow keys\nand to choose target firm version\n"); - - const u32 o_ver[6] = {17120, 18182, 19216, 20262, 21288, 22313}; - const u32 n_ver[6] = {17120, 18182, 19218, 20262, 21288, 22313}; - - const char* versions[6] = { - "(9.0 - 9.2) ", - "(9.3 - 9.4) ", - "(9.5) ", - "(9.6 - 9.9) ", - "(10.0 - 10.1)", - "(10.2 - 10.3)" - }; - - int idx = 0; - while (true) { - iprintf("\rv%d %s", (device ? n_ver[idx] : o_ver[idx]), versions[idx]); - - scanKeys(); - u32 keys = keysDown(); - if (keys & KEY_UP) { - idx -= 1; - if (idx < 0) { - idx = 0; - } - } else if (keys & KEY_DOWN) { - idx += 1; - if (idx > 5) { - idx = 5; - } - } else if (keys & KEY_A) { - iprintf("\n\n"); - return device ? n_ver[idx] : o_ver[idx]; - } else if (keys & KEY_B) { - iprintf("\r(cancelled by user)\n\n"); - return -1; - } - - swiWaitForVBlank(); - } -} - -int patch() { - int8_t device = selectDeviceType(); - if (device < 0) { - return -1; - } - - int32_t version = selectFirmVersion(device); - if (version < 0) { - return -1; - } - - struct ntrcardhax_info *info; - for (int i = 0; i < 6; i++) { - struct ntrcardhax_info *tmp = device - ? &n_ak2i_ntrcardhax_infos[i] - : &o_ak2i_ntrcardhax_infos[i]; - if (tmp->version == version) { - info = tmp; - break; - } - } - - memcpy(payload, bootrom + AK2I_PAYLOAD_OFFSET, AK2I_PAYLOAD_LENGTH); - - // see https://github.com/peteratebs/rtfsprofatfilesystem/blob/b0003c4/include/rtfstypes.h#L1468-L1549 - int rtfsCfgAdrDiff = info->rtfs_cfg_addr - info->ntrcard_header_addr; - // use ~ drno_to_dr_map - int rtfsCopyLen = 0x144; - - int wrappedAdr = (rtfsCfgAdrDiff) & 0xFFF; - - if ((wrappedAdr >= 0x0) && (wrappedAdr <= 0x10)) { - iprintf("Conflict ntrcard header"); - return -1; - } - if ((wrappedAdr >= 0x2A8) && (wrappedAdr <= 0x314)) { - iprintf("Conflict rtfs struct"); - return -1; - } - - uint32_t rtfs_cfg[0x144] = {0}; - // cfg_NFINODES - rtfs_cfg[5] = 1; - // mem_region_pool - rtfs_cfg[17] = (uint32_t)(info->ntrcard_header_addr + 0x4); - int i; - // drno_to_dr_map - for (i = 0; i < 26; i++) - rtfs_cfg[55 + i] = (uint32_t)(info->ntrcard_header_addr + 0); - - uint32_t* prtfs_cfg32 = rtfs_cfg; - - for (i = 0; i < rtfsCopyLen; i+=4) { - wrappedAdr = (rtfsCfgAdrDiff + i) & 0xFFF; - //printf("addr: %08X data: %08X\n", wrappedAdr, prtfs_cfg32[i/4]); - if((wrappedAdr >= 0x14) && (wrappedAdr <= 0x60)) { - //if(i < 0xFC) { - // iprintf("Not enough buffer"); - // return -1; - //} - break; - } - *(uint32_t*)&payload[wrappedAdr] = prtfs_cfg32[i/4]; - } - - *(uint32_t*)&payload[0x2EC] = info->rtfs_handle_addr; //Some handle rtfs uses - *(uint32_t*)&payload[0x2F0] = 0x41414141; //Bypass FAT corruption error - *(uint32_t*)&payload[0x31C] = info->ntrcard_header_addr + 0x2A8; //This is the PC we want to jump to (from a BLX) - - memcpy(&payload[0x2A8], loader_bin, 0x44); - - uint16_t crc = calcCrc(payload, 0x15E); - *(uint16_t*)&payload[0x15E] = crc; - - memcpy(bootrom + AK2I_PAYLOAD_OFFSET, payload, AK2I_PAYLOAD_LENGTH); - - iprintf("crc: %x\n", crc); - - return 0; -} - int inject() { - u32 chipid = getChipID(); - if (chipid != 0xFC2) { - iprintf("Cartridge is not AK2i\n"); - return -1; - } + Flashcart *cart = waitCartReady(); - u32 hwid = getHWID(); - if (hwid != 0x81 && hwid != 0x44 ) { - iprintf("Cartridge is not AK2i\n"); + u8 deviceType = selectDeviceType(); + if (deviceType < 0) { return -1; } - iprintf("Cart: 0x%04X HW: %x\n", chipid, hwid); - - setMapTableAddress(AK2I_MTN_NOR_OFFSET, 0); - - // setup flash to 1681 - if (hwid == 0x81) { - iprintf("Setup flash to 1681\n"); - setFlash1681_81(); - } - - iprintf("Active FAT MAP\n"); - // have to do this on ak2i before making fatmap, or the first 128k flash data will be screwed up. - activeFatMap(); - - iprintf("Unlock flash\n"); - // this funcion write enable only above 0x40000 on ak2i, write enable all on ak2 - unlockFlash(); - - iprintf("Unlock ASIC\n"); - // unlock 0x30000 for save map, see definition of NOR_FAT2_START above - unlockASIC(); - - iprintf("Erase flash\n"); - for (u32 i = 0; i < AK2I_PATCH_LENGTH; i += 64 * 1024) { - if (hwid == 0x81) { - eraseFlashBlock_81(i); - } else { - eraseFlashBlock_44(i); - } - } - //ioAK2EraseFlash( 0, CHIP_ERASE ); - - //buffer[0x200C] = 'B'; - - iprintf("Writing...\n"); - - int old = 0; - - iprintf("%0"); - for (u32 i = 0; i < AK2I_PATCH_LENGTH; i += 512) { - int curr = percent(i, AK2I_PATCH_LENGTH); - if (curr != old && curr % 5 == 0) { - iprintf("\r%d%%", curr); - old = curr; - } - if (hwid == 0x81) { - writeFlash_81(i, bootrom + i, 512); - } else { - writeFlash_44(i, bootrom + i, 512); - } - - if (!verifyFlash(bootrom + i, i, 512)) { - iprintf("verify failed at %08X\n", i); - } + u8 *buf = dump(cart); + if (!buf) { + return -1; } - iprintf("\r100%%\n"); - iprintf("Lock flash\n"); - lockFlash(); + u8 *blowfish_key = deviceType ? blowfish_dev_bin : blowfish_retail_bin; + u8 *firm = deviceType ? boot9strap_dev_firm : boot9strap_ntr_firm; + u32 firm_size = deviceType ? boot9strap_dev_firm_size : boot9strap_ntr_firm_size; - iprintf("Done\n\n"); + iprintf("\n"); + ShowProgress(0, 0, 1); + cart->writeBlowfishAndFirm(blowfish_key, firm, firm_size); + ShowProgress(0, 1, 1); + cart->cleanup(); + iprintf("\nDone\n\n"); return 0; } - -void patchAndInject() { - if (patch() < 0) { - iprintf("Failed\n\n"); - return; - } - - if (inject() < 0) { - iprintf("Failed\n\n"); - return; - } -} - -void injectOriginal() { - memcpy(bootrom + AK2I_PAYLOAD_OFFSET, orig_header, AK2I_PAYLOAD_LENGTH); - - if (inject() < 0) { - iprintf("Failed\n\n"); - return; - } -} - int main(void) { consoleDemoInit(); sysSetBusOwners(true, true); // give ARM9 access to the cart - iprintf("AK2I ntrcardhax injector\n"); - iprintf("* application will remove *\n"); - iprintf("* nds flashcart feature *\n"); - iprintf("* if you want recover, *\n"); - iprintf("* need another flashcart *\n"); + iprintf("= AK2I NTRBOOTHAX FLASHER =\n\n"); - pause(); - - waitCartReady(); - - // preload - if (dump() < 0) { - iprintf("Failed\n\n"); - pause(); - return 0; - } + iprintf("* if you use non ak2i *\n"); + iprintf("* you will lost flashcart *\n"); + iprintf("* feature. *\n"); + iprintf("* DO NOT CLOSE THIS APP *\n"); + iprintf("* IF YOU DONT HAVE SAME *\n"); + iprintf("* FLASHCART *\n"); + waitPressA(); while (true) { iprintf("You can swap flashcart for flash\n"); - iprintf("A. inject ntrcardhax\n"); - iprintf("X. restore original bootrom\n"); + iprintf("A. inject ntrboothax\n"); + iprintf("X. restore flashcart\n"); iprintf("B. exit\n\n"); while (true) { @@ -490,10 +210,7 @@ int main(void) { u32 keys = keysDown(); if (keys & KEY_A) { - patchAndInject(); - break; - } else if (keys & KEY_X) { - injectOriginal(); + inject(); break; } else if (keys & KEY_B) { return 0; From b660fd676180f3972f5355890880f032b4e5880b Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Mon, 14 Aug 2017 01:37:38 +0900 Subject: [PATCH 4/8] Implement restore --- Makefile | 2 +- source/gamecart.cpp | 29 +++++++- source/main.cpp | 176 ++++++++++++++++++++++---------------------- 3 files changed, 116 insertions(+), 91 deletions(-) diff --git a/Makefile b/Makefile index 45195dd..78c250f 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ include $(DEVKITARM)/ds_rules #--------------------------------------------------------------------------------- TARGET := $(shell basename $(CURDIR)) BUILD := build -SOURCES := source external/flashcart_core +SOURCES := source external/flashcart_core external/flashcart_core/devices DATA := data INCLUDES := include external diff --git a/source/gamecart.cpp b/source/gamecart.cpp index 088cfd3..0b0c509 100644 --- a/source/gamecart.cpp +++ b/source/gamecart.cpp @@ -7,8 +7,12 @@ void Cart_NTRInit() { } -void NTR_SendCommand(const u8 *command, u32 length, u32 flags, u8 *destination) { - cardWriteCommand(command); +void NTR_SendCommand(const u8 *command, u32 length, u32 unk, u8 *destination) { + u8 reversed[8]; + for (int i = 0; i < 8; i++) { + reversed[7 - i] = command[i]; + } + u32 defaultFlags; switch (length & 0xfffffffc) { case 0: @@ -30,9 +34,26 @@ void NTR_SendCommand(const u8 *command, u32 length, u32 flags, u8 *destination) defaultFlags = CARD_BLK_SIZE(4); break; } + + /* + switch(command[0]) { + case 0xB7: + defaultFlags |= CARD_DELAY1(2); + break; + case 0xC0: + defaultFlags |= CARD_DELAY1(4); + break; + case 0xC8: + case 0xD4: + case 0xD8: + defaultFlags |= CARD_DELAY1(20); + break; + } + */ + // NDSL only - cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET, - (u32*)destination, length, command); + cardPolledTransfer(defaultFlags | CARD_ACTIVATE | CARD_nRESET, + (u32*)destination, length, reversed); // NDSL, DSLi, etc... //cardPolledTransfer(flags | defaultFlags | CARD_ACTIVATE | CARD_nRESET | // CARD_SEC_CMD | CARD_SEC_EN | CARD_SEC_DAT, diff --git a/source/main.cpp b/source/main.cpp index 893d4ca..4541656 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -8,43 +8,9 @@ #include "flashcart_core/device.h" #include "binaries.h" -u8 *orig_flashrom; - -static uint16_t crc16tab[] = -{ - 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241, - 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440, - 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40, - 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841, - 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40, - 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41, - 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641, - 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040, - 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240, - 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441, - 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41, - 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840, - 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41, - 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40, - 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640, - 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041, - 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240, - 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441, - 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41, - 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840, - 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41, - 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40, - 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640, - 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041, - 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241, - 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440, - 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40, - 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841, - 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40, - 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41, - 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641, - 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040 -}; +// FIXME: not fully overwrite +u8 orig_flashrom[0xA0000] = {0}; +u8 restorable = 0; void waitPressA() { iprintf("press \n\n"); @@ -69,7 +35,7 @@ Flashcart* waitCartReady() { cart = Flashcart::detectCart(); } while(!cart); - iprintf("Detected: %s", cart->getDescription()); + iprintf("Detected: %s\n\n", cart->getDescription()); return cart; } @@ -79,54 +45,29 @@ int percent(int c, int t) { } void ShowProgress(char screen, uint32_t curr, uint32_t total) { - if (curr * 100 % total) { - return; - } - - iprintf("\r%3d%%", curr * 100 / total); + static int old = 100; + int pct = percent(curr, total); + if (pct % 5 == 0 && old != pct); + iprintf("\r %3d%%", pct); + old = pct; } -uint16_t calcCrc(u8 *data, uint32_t length) -{ - uint16_t crc = (uint16_t)~0; - for(unsigned int i = 0; i> 8) ^ crc16tab[(crc ^ data[i]) & 0xFF]; - } - return crc; -} - -u8* dump(Flashcart *cart) { +u8 dump(Flashcart *cart) { u32 length = cart->getMaxLength(); - - if (orig_flashrom) { - iprintf("already loaded original rom\n"); - iprintf("if continue, you will lost this data\n"); - iprintf("and you can lost restore chance\n"); - iprintf("Y. continue\n"); - iprintf("A. exit\n"); - - while (true) { - scanKeys(); - u32 keys = keysDown(); - - if (keys & KEY_A) { - return NULL; - } else if (keys & KEY_Y) { - break; - } - swiWaitForVBlank(); - } - free(orig_flashrom); + if (length > 0xA0000) { + length = 0xA0000; } - - orig_flashrom = static_cast(malloc(sizeof(u8) * length)); - memset(orig_flashrom, 0, sizeof(u8) * length); + iprintf("%d\n", length); + memset(orig_flashrom, 0, 0xA0000); u8 *temp = orig_flashrom; - iprintf("\n"); + + iprintf("Dump original flashrom\n"); ShowProgress(0, 0, 1); cart->readFlash(0, length, temp); + cart->cleanup(); ShowProgress(0, 1, 1); + + restorable = 1; iprintf("\nDone\n\n"); return 0; @@ -137,7 +78,7 @@ int8_t selectDeviceType() { u8 is_dev = 0; while (true) { - iprintf("\r%s", is_dev ? "DEV" : "RETAIL"); + iprintf("\r%s", is_dev ? "DEV " : "RETAIL"); scanKeys(); u32 keys = keysDown(); @@ -154,17 +95,45 @@ int8_t selectDeviceType() { } } +int load() { + if (restorable) { + iprintf("already loaded original rom\n"); + iprintf("you will lost this data\n"); + iprintf("and you can lost restore chance\n"); + iprintf("Y. continue\n"); + iprintf("A. cancel\n"); + + while (true) { + scanKeys(); + u32 keys = keysDown(); + + if (keys & KEY_A) { + return -1; + } else if (keys & KEY_Y) { + break; + } + swiWaitForVBlank(); + } + } -int inject() { Flashcart *cart = waitCartReady(); + return dump(cart); +} - u8 deviceType = selectDeviceType(); - if (deviceType < 0) { +int inject() { + if (!restorable) { + iprintf("you haven't load firmware\n"); + iprintf("it can make to lost flashcart\n"); + iprintf("feature\n"); + iprintf("please load first\n"); + waitPressA(); return -1; } - u8 *buf = dump(cart); - if (!buf) { + Flashcart *cart = waitCartReady(); + + u8 deviceType = selectDeviceType(); + if (deviceType < 0) { return -1; } @@ -172,13 +141,41 @@ int inject() { u8 *firm = deviceType ? boot9strap_dev_firm : boot9strap_ntr_firm; u32 firm_size = deviceType ? boot9strap_dev_firm_size : boot9strap_ntr_firm_size; - iprintf("\n"); + iprintf("Flash ntrboothax\n"); ShowProgress(0, 0, 1); cart->writeBlowfishAndFirm(blowfish_key, firm, firm_size); + cart->cleanup(); + ShowProgress(0, 1, 1); + iprintf("\nDone\n\n"); + + return 0; +} + +int restore() { + Flashcart *cart = waitCartReady(); + + if (!restorable) { + iprintf("Not loaded original flashrom\n"); + return -1; + } + + iprintf("Restore original flash\n"); + + u32 length = cart->getMaxLength(); + if (length > 0xA0000) { + length = 0xA0000; + } + + // FIXME: it's fully overwrite. + // 3ds version use check and flash if that mismatched + // how about this? + ShowProgress(0, 0, 1); + cart->writeFlash(0, length, orig_flashrom); ShowProgress(0, 1, 1); cart->cleanup(); iprintf("\nDone\n\n"); + // TODO verify check return 0; } @@ -201,8 +198,9 @@ int main(void) { while (true) { iprintf("You can swap flashcart for flash\n"); + iprintf("X. load flashrom\n"); iprintf("A. inject ntrboothax\n"); - iprintf("X. restore flashcart\n"); + iprintf("Y. restore flashrom\n"); iprintf("B. exit\n\n"); while (true) { @@ -212,6 +210,12 @@ int main(void) { if (keys & KEY_A) { inject(); break; + } else if (keys & KEY_X) { + load(); + break; + } else if (keys & KEY_Y) { + restore(); + break; } else if (keys & KEY_B) { return 0; } From 13cfdbd974accb02777aa3b384ede807311d4171 Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Mon, 14 Aug 2017 01:41:38 +0900 Subject: [PATCH 5/8] Comment out restore It occur brick --- source/main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 4541656..73527a3 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -200,7 +200,7 @@ int main(void) { iprintf("You can swap flashcart for flash\n"); iprintf("X. load flashrom\n"); iprintf("A. inject ntrboothax\n"); - iprintf("Y. restore flashrom\n"); +// iprintf("Y. restore flashrom\n"); iprintf("B. exit\n\n"); while (true) { @@ -213,9 +213,9 @@ int main(void) { } else if (keys & KEY_X) { load(); break; - } else if (keys & KEY_Y) { - restore(); - break; +// } else if (keys & KEY_Y) { +// restore(); +// break; } else if (keys & KEY_B) { return 0; } From 81484cf7c7c834e72614a53befb6a1f249f38f4a Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Mon, 14 Aug 2017 02:13:23 +0900 Subject: [PATCH 6/8] Fix wrong firm for dev device --- source/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/main.cpp b/source/main.cpp index 73527a3..bf22f5c 100644 --- a/source/main.cpp +++ b/source/main.cpp @@ -138,8 +138,8 @@ int inject() { } u8 *blowfish_key = deviceType ? blowfish_dev_bin : blowfish_retail_bin; - u8 *firm = deviceType ? boot9strap_dev_firm : boot9strap_ntr_firm; - u32 firm_size = deviceType ? boot9strap_dev_firm_size : boot9strap_ntr_firm_size; + u8 *firm = deviceType ? boot9strap_ntr_dev_firm : boot9strap_ntr_firm; + u32 firm_size = deviceType ? boot9strap_ntr_dev_firm_size : boot9strap_ntr_firm_size; iprintf("Flash ntrboothax\n"); ShowProgress(0, 0, 1); From db6e6e364b89e7d7dbee3ea594528961d094a317 Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Mon, 14 Aug 2017 02:15:20 +0900 Subject: [PATCH 7/8] Update .gitignore --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index bd8b8e6..cd85336 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ *.elf *.nds build/ +binaries/ +include/binaries.h From 9e422cd86d10f566b10af4a3803c004f0c90e0e2 Mon Sep 17 00:00:00 2001 From: Sunguk Lee Date: Mon, 14 Aug 2017 02:15:32 +0900 Subject: [PATCH 8/8] Add README --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f540d6a --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +## NDS version NTRBOOTHAX flasher +Only tested NDSL + AK2I + +DO NOT USE THIS ON NDSI + +### Known issues +* Probably cannot use with non AK2I cart. + + We should make NDSI mode instead NDS. But that mode cannot use cartridge + swap, and probably lost flashcart feature until someone provide restore + image. + +* Removed restore feature, I don't know reason, flasher occur cartridge brick. + + But, AK2I will work as flashcart whenever flashed or not. + So, just feature blocked. + +### Build +1. copy these 4 binaries to `binaries` directory. + - `blowfish_dev.bin` + - `blowfish_retail.bin` + - `boot9strap_ntr_dev.firm` + - `boot9strap_ntr.firm` +2. `python extract_binaries.py` +3. then `make` + +### Credits +* [Normmatt][normmatt] - Original implement 3DS version ntrcardhax flasher +* [SciresM][sciresm] - Parent of `boot9strap` +* [kitling][kitling] - Made `flashcart_core` +* [hedgeberg][hedgeberg] - RE Cartridge