|
10 | 10 | #include "fs.h"
|
11 | 11 | #include "utils.h"
|
12 | 12 | #include "nand.h"
|
| 13 | +#include "gamecart.h" |
13 | 14 | #include "virtual.h"
|
14 | 15 | #include "vcart.h"
|
15 | 16 | #include "game.h"
|
@@ -959,6 +960,67 @@ u32 StandardCopy(u32* cursor, u32* scroll) {
|
959 | 960 | return 0;
|
960 | 961 | }
|
961 | 962 |
|
| 963 | +u32 CartRawDump(void) { |
| 964 | + CartData* cdata = (CartData*) malloc(sizeof(CartData)); |
| 965 | + char dest[256]; |
| 966 | + char cname[24]; |
| 967 | + char bytestr[32]; |
| 968 | + u64 dsize = 0; |
| 969 | + |
| 970 | + if (!cdata ||(InitCartRead(cdata) != 0) || (GetCartName(cname, cdata) != 0)) { |
| 971 | + ShowPrompt(false, "Cart init failed!"); |
| 972 | + free(cdata); |
| 973 | + return 1; |
| 974 | + } |
| 975 | + |
| 976 | + // input dump size |
| 977 | + dsize = cdata->cart_size; |
| 978 | + FormatBytes(bytestr, dsize); |
| 979 | + dsize = ShowHexPrompt(dsize, 8, "Cart: %s\nDetected size: %s\n \nInput dump size below.", cname, bytestr); |
| 980 | + if (!dsize || (dsize == (u64) -1)) { |
| 981 | + free(cdata); |
| 982 | + return 1; |
| 983 | + } |
| 984 | + |
| 985 | + // for NDS carts: ask for secure area encryption |
| 986 | + if (cdata->cart_type & CART_NTR) |
| 987 | + SetSecureAreaEncryption( |
| 988 | + !ShowPrompt(true, "Cart: %s\nNDS cart detected\nDecrypt the secure area?", cname)); |
| 989 | + |
| 990 | + // destination path |
| 991 | + snprintf(dest, 256, "%s/%s_%08llX.%s", |
| 992 | + OUTPUT_PATH, cname, dsize, (cdata->cart_type & CART_CTR) ? "3ds" : "nds"); |
| 993 | + |
| 994 | + // buffer allocation |
| 995 | + u8* buf = (u8*) malloc(STD_BUFFER_SIZE); |
| 996 | + if (!buf) { // this will not happen |
| 997 | + free(cdata); |
| 998 | + return 1; |
| 999 | + } |
| 1000 | + |
| 1001 | + // actual cart dump |
| 1002 | + u32 ret = 0; |
| 1003 | + PathDelete(dest); |
| 1004 | + ShowProgress(0, 0, cname); |
| 1005 | + for (u64 p = 0; p < dsize; p += STD_BUFFER_SIZE) { |
| 1006 | + u64 len = min((dsize - p), STD_BUFFER_SIZE); |
| 1007 | + if ((ReadCartBytes(buf, p, len, cdata, false) != 0) || |
| 1008 | + (fvx_qwrite(dest, buf, p, len, NULL) != FR_OK) || |
| 1009 | + !ShowProgress(p, dsize, cname)) { |
| 1010 | + PathDelete(dest); |
| 1011 | + ret = 1; |
| 1012 | + break; |
| 1013 | + } |
| 1014 | + } |
| 1015 | + |
| 1016 | + if (ret) ShowPrompt(false, "%s\nFailed dumping cart", cname); |
| 1017 | + else ShowPrompt(false, "%s\nDumped to %s", cname, OUTPUT_PATH); |
| 1018 | + |
| 1019 | + free(buf); |
| 1020 | + free(cdata); |
| 1021 | + return ret; |
| 1022 | +} |
| 1023 | + |
962 | 1024 | u32 DirFileAttrMenu(const char* path, const char *name) {
|
963 | 1025 | bool drv = (path[2] == '\0');
|
964 | 1026 | bool vrt = (!drv); // will be checked below
|
@@ -2488,11 +2550,13 @@ u32 GodMode(int entrypoint) {
|
2488 | 2550 | ((GetMountState() == IMG_NAND) && (*(curr_entry->path) == '7')))) ? ++n_opt : -1;
|
2489 | 2551 | int dirnfo = ++n_opt;
|
2490 | 2552 | int stdcpy = (*current_path && strncmp(current_path, OUTPUT_PATH, 256) != 0) ? ++n_opt : -1;
|
| 2553 | + int rawdump = (!*current_path && (DriveType(curr_entry->path) & DRV_CART)) ? ++n_opt : -1; |
2491 | 2554 | if (tman > 0) optionstr[tman-1] = "Open title manager";
|
2492 | 2555 | if (srch_f > 0) optionstr[srch_f-1] = "Search for files...";
|
2493 | 2556 | if (fixcmac > 0) optionstr[fixcmac-1] = "Fix CMACs for drive";
|
2494 | 2557 | if (dirnfo > 0) optionstr[dirnfo-1] = (*current_path) ? "Show directory info" : "Show drive info";
|
2495 | 2558 | if (stdcpy > 0) optionstr[stdcpy-1] = "Copy to " OUTPUT_PATH;
|
| 2559 | + if (rawdump > 0) optionstr[rawdump-1] = "Dump to " OUTPUT_PATH; |
2496 | 2560 | char namestr[UTF_BUFFER_BYTESIZE(32)];
|
2497 | 2561 | TruncateString(namestr, (*current_path) ? curr_entry->path : curr_entry->name, 32, 8);
|
2498 | 2562 | int user_select = ShowSelectPrompt(n_opt, optionstr, "%s", namestr);
|
@@ -2527,6 +2591,8 @@ u32 GodMode(int entrypoint) {
|
2527 | 2591 | }
|
2528 | 2592 | } else if (user_select == stdcpy) {
|
2529 | 2593 | StandardCopy(&cursor, &scroll);
|
| 2594 | + } else if (user_select == rawdump) { |
| 2595 | + CartRawDump(); |
2530 | 2596 | }
|
2531 | 2597 | } else { // one level up
|
2532 | 2598 | u32 user_select = 1;
|
|
0 commit comments