u32 DecryptNandPartition(u32 param) { PartitionInfo* p_info = NULL; char filename[64]; u8 magic[NAND_SECTOR_SIZE]; for (u32 partition_id = P_TWLN; partition_id <= P_CTRNAND; partition_id = partition_id << 1) { if (param & partition_id) { p_info = GetPartitionInfo(partition_id); break; } } if (p_info == NULL) { Debug("No partition to dump"); return 1; } Debug("Dumping & Decrypting %s, size (MB): %u", p_info->name, p_info->size / (1024 * 1024)); if (DecryptNandToMem(magic, p_info->offset, 16, p_info) != 0) return 1; if ((p_info->magic[0] != 0xFF) && (memcmp(p_info->magic, magic, 8) != 0)) { Debug("Decryption error, please contact us"); return 1; } if (OutputFileNameSelector(filename, p_info->name, "bin", param & N_EMUNAND) != 0) return 1; return DecryptNandToFile(filename, p_info->offset, p_info->size, p_info); }
u32 DumpHealthAndSafety(u32 param) { (void) (param); // param is unused here PartitionInfo* ctrnand_info = GetPartitionInfo(P_CTRNAND); TitleListInfo* health = titleList + ((GetUnitPlatform() == PLATFORM_3DS) ? 3 : 4); TitleListInfo* health_alt = (GetUnitPlatform() == PLATFORM_N3DS) ? titleList + 3 : NULL; char filename[64]; u32 offset_app[4]; u32 size_app[4]; u32 offset_tmd; u32 size_tmd; if ((DebugSeekTitleInNand(&offset_tmd, &size_tmd, offset_app, size_app, health, 4) != 0) && (!health_alt || (DebugSeekTitleInNand(&offset_tmd, &size_tmd, offset_app, size_app, health_alt, 4) != 0))) return 1; if (OutputFileNameSelector(filename, "hs.app", NULL) != 0) return 1; Debug("Dumping & decrypting APP0..."); if (DecryptNandToFile(filename, offset_app[0], size_app[0], ctrnand_info) != 0) return 1; if (CryptNcch(filename, 0, 0, 0, NULL) != 0) return 1; return 0; }
u32 DumpNand(u32 param) { char filename[64]; u8* buffer = BUFFER_ADDRESS; u32 nand_size = getMMCDevice(0)->total_size * NAND_SECTOR_SIZE; u32 result = 0; Debug("Dumping %sNAND. Size (MB): %u", (param & N_EMUNAND) ? "Emu" : "Sys", nand_size / (1024 * 1024)); if (OutputFileNameSelector(filename, "NAND.bin", NULL, param & N_EMUNAND) != 0) return 1; if (!DebugFileCreate(filename, true)) return 1; u32 n_sectors = nand_size / NAND_SECTOR_SIZE; for (u32 i = 0; i < n_sectors; i += SECTORS_PER_READ) { u32 read_sectors = min(SECTORS_PER_READ, (n_sectors - i)); ShowProgress(i, n_sectors); ReadNandSectors(i, read_sectors, buffer); if(!DebugFileWrite(buffer, NAND_SECTOR_SIZE * read_sectors, i * NAND_SECTOR_SIZE)) { result = 1; break; } } ShowProgress(0, 0); FileClose(); return result; }
u32 DumpFile(u32 param) { NandFileInfo* f_info = GetNandFileInfo(param); PartitionInfo* p_info = GetPartitionInfo(f_info->partition_id); char filename[64]; u32 offset; u32 size; if (DebugSeekFileInNand(&offset, &size, f_info->name_l, f_info->path, p_info) != 0) return 1; if (OutputFileNameSelector(filename, f_info->name_l, NULL) != 0) return 1; if (DecryptNandToFile(filename, offset, size, p_info) != 0) return 1; return 0; }