int get_emunand_offsets(uint32_t location, uint32_t *offset, uint32_t *header) { if (sdmmc_sdcard_readsectors(location + 1, 1, fcram_temp) == 0) { if (*(uint32_t *)(fcram_temp + 0x100) == NCSD_MAGIC) { if (offset && header) { print("emuNAND detected: redNAND"); *offset = location + 1; *header = location + 1; } return 0; } } uint32_t nand_size = getMMCDevice(0)->total_size; if (sdmmc_sdcard_readsectors(location + nand_size, 1, fcram_temp) == 0) { if (*(uint32_t *)(fcram_temp + 0x100) == NCSD_MAGIC) { if (offset && header) { print("emuNAND detected: Gateway"); *offset = location; *header = location + nand_size; } return 0; } } return 1; }
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND) { static u8 *const temp = (u8 *)0x24300000; const u32 nandSize = getMMCDevice(0)->total_size; u32 nandOffset = *emuNAND == 1 ? 0 : (nandSize > 0x200000 ? 0x400000 : 0x200000); //Check for RedNAND if(!sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) && *(u32 *)(temp + 0x100) == NCSD_MAGIC) { *off = nandOffset + 1; *head = nandOffset + 1; } //Check for Gateway emuNAND else if(!sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) && *(u32 *)(temp + 0x100) == NCSD_MAGIC) { *off = nandOffset; *head = nandOffset + nandSize; } /* Fallback to the first emuNAND if there's no second one, or to SysNAND if there isn't any */ else { (*emuNAND)--; if(*emuNAND) getEmunandSect(off, head, emuNAND); } }
u32 CheckEmuNand(void) { u8* buffer = BUFFER_ADDRESS; u32 nand_size_sectors = getMMCDevice(0)->total_size; u32 nand_offset; if (emunand_no > 0) { if (nand_size_sectors > EMUNAND_MULTI_OFFSET_O3DS) { nand_offset = EMUNAND_MULTI_OFFSET_N3DS * (emunand_no - 1 ); } else { nand_offset = EMUNAND_MULTI_OFFSET_O3DS * (emunand_no - 1 ); } } else { nand_offset = 0; } // check the MBR for presence of EmuNAND sdmmc_sdcard_readsectors(0, 1, buffer); if (nand_offset+nand_size_sectors > getle32(buffer + 0x1BE + 0x8)) return EMUNAND_NOT_READY; // check for Gateway type EmuNAND sdmmc_sdcard_readsectors(nand_offset+nand_size_sectors, 1, buffer); if (memcmp(buffer + 0x100, "NCSD", 4) == 0) return EMUNAND_GATEWAY; // check for RedNAND type EmuNAND sdmmc_sdcard_readsectors(nand_offset + 1, 1, buffer); if (memcmp(buffer + 0x100, "NCSD", 4) == 0) return EMUNAND_REDNAND; // EmuNAND ready but not set up return EMUNAND_READY; }
u32 SetNand(bool set_emunand, bool force_emunand) { if (set_emunand) { u32 emunand_state = CheckEmuNand(); if ((emunand_state == EMUNAND_READY) && force_emunand) emunand_state = EMUNAND_GATEWAY; switch (emunand_state) { case EMUNAND_NOT_READY: Debug("SD is not formatted for EmuNAND"); return 1; case EMUNAND_GATEWAY: emunand_header = getMMCDevice(0)->total_size; emunand_offset = 0; Debug("Using EmuNAND @ %06X/%06X", emunand_header, emunand_offset); return 0; case EMUNAND_REDNAND: emunand_header = 1; emunand_offset = 1; Debug("Using RedNAND @ %06X/%06X", emunand_header, emunand_offset); return 0; default: Debug("EmuNAND is not available"); return 1; } } else { emunand_header = 0; emunand_offset = 0; 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; }
void getEmunandSect(u32 *off, u32 *head, u32 *emuNAND) { u8 *const temp = (u8 *)0x24300000; const u32 nandSize = getMMCDevice(0)->total_size; u32 nandOffset = *emuNAND == 1 ? 0 : (nandSize > 0x200000 ? 0x400000 : 0x200000); //Check for RedNAND if(sdmmc_sdcard_readsectors(nandOffset + 1, 1, temp) == 0) { if(*(u32 *)(temp + 0x100) == NCSD_MAGIC) { *off = nandOffset + 1; *head = nandOffset + 1; } //Check for Gateway emuNAND else if(sdmmc_sdcard_readsectors(nandOffset + nandSize, 1, temp) == 0) { if(*(u32 *)(temp + 0x100) == NCSD_MAGIC) { *off = nandOffset; *head = nandOffset + nandSize; } //Fallback to the first emuNAND if there's no second one else if(*emuNAND == 2) { *emuNAND = 1; getEmunandSect(off, head, emuNAND); } else *emuNAND = 0; } } }
void getEmunandSect(u32 *off, u32 *head){ u32 nandSize = getMMCDevice(0)->total_size; if (sdmmc_sdcard_readsectors(nandSize, 1, temp) == 0) { if (*(u32*)(temp + 0x100) == NCSD_MAGIC) { *off = 0; *head = nandSize; } } }
void menu_emunand() { char emunands[MAX_OPTIONS][0x20]; // We have a max size for the strings... char unnamed[] = "emuNAND #"; uint32_t gap; if (getMMCDevice(0)->total_size > 0x200000) { gap = 0x400000; } else { gap = 0x200000; } // Scan for available emuNANDS. Assume they're placed right behind eachother. int count; for (count = 0; count <= MAX_OPTIONS; count++) { if (get_emunand_offsets(count * gap, NULL, NULL) == 0) { if (sdmmc_sdcard_readsectors(count * gap, 1, fcram_temp) == 0 && memcmp(fcram_temp + 11, "NAME", 4) == 0) { memcpy(emunands[count], fcram_temp + 15, 0x1F); emunands[count][0x1F] = 0; } else { memcpy(emunands[count], unnamed, sizeof(unnamed)); emunands[count][sizeof(unnamed) - 1] = '1' + count; emunands[count][sizeof(unnamed)] = 0; } continue; } break; } if (count <= 0) { print("Failed to find any emuNAND"); draw_message("Failed to find any emuNAND", "There's 3 possible causes for this error:\n" " - You don't even have an emuNAND installed\n" " - Your SD card can't be read\n" " - You're using an unsupported emuNAND format"); return; } // Make the pointer array char *options[count]; for (int x = 0; x <= count; x++) options[x] = emunands[x]; int result = draw_menu("Select emuNAND", 1, count, options); if (result == -1) return; config->emunand_location = result * gap; patches_modified = 1; }
int REDNAND(void){ u8 buf[0x200]; sdmmc_sdcard_readsectors(1, 1, buf); //"rednand" if (strncmp((char *)(buf+0x100), "NCSD", 4) == 0){ emunand_code[22] = 1; emunand_code[23] = 1; return 0; } mmcdevice *nand = getMMCDevice(0); sdmmc_sdcard_readsectors(nand->total_size, 1, buf); //"emunand" if (strncmp((char *)(buf+0x100), "NCSD", 4) == 0){ emunand_code[22] = 0; emunand_code[23] = nand->total_size; return 0; } return -1; }
u32 CheckEmuNand(void) { u8* buffer = BUFFER_ADDRESS; u32 nand_size_sectors = getMMCDevice(0)->total_size; // check the MBR for presence of EmuNAND sdmmc_sdcard_readsectors(0, 1, buffer); if (nand_size_sectors > getle32(buffer + 0x1BE + 0x8)) return EMUNAND_NOT_READY; // check for Gateway type EmuNAND sdmmc_sdcard_readsectors(nand_size_sectors, 1, buffer); if (memcmp(buffer + 0x100, "NCSD", 4) == 0) return EMUNAND_GATEWAY; // check for RedNAND type EmuNAND sdmmc_sdcard_readsectors(1, 1, buffer); if (memcmp(buffer + 0x100, "NCSD", 4) == 0) return EMUNAND_REDNAND; // EmuNAND ready but not set up return EMUNAND_READY; }
uint64_t ctr_sd_interface_disk_size(void *io) { return getMMCDevice(1)->total_size * (uint64_t)512u; }