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); } }
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; } } }
//Load firm into FCRAM void loadFirm(void){ //Read FIRM from SD card and write to FCRAM fopen("/rei/firmware.bin"); firmSize = fsize(); fread(firmLocation, 1, firmSize); fclose(); decryptFirm(firmLocation, firmSize); //Initial setup firm = firmLocation; section = firm->section; k9loader(firmLocation + section[2].offset); //Check for Emunand getEmunandSect(&emuOffset, &emuHeader); if(emuOffset || emuHeader) loadEmu(); else loadSys(); }
//Load firm into FCRAM void loadFirm(void){ //Read FIRM from SD card and write to FCRAM fopen("/rei/firmware.bin", "rb"); firmSize = fsize()/2; if(PDN_MPCORE_CFG == 1) fseek(firmSize); fread(firmLocation, 1, firmSize); fclose(); decryptFirm(firmLocation, firmSize); //Initial setup firm = firmLocation; section = firm->section; keyInit(firmLocation + section[2].offset); //Set MPU for emu/thread code region getMPU(firmLocation, firmSize, &mpuOffset); memcpy((u8*)mpuOffset, mpu, sizeof(mpu)); //Inject custom loader fopen("/rei/loader.cxi", "rb"); u8 *arm11SysMods = (u8 *)firm + section[0].offset; Size ldrInFirmSize; Size ldrFileSize = fsize(); getLoader(arm11SysMods, &ldrInFirmSize, &ldrOffset); memcpy(section[0].address, arm11SysMods, ldrOffset); fread(section[0].address + ldrOffset, 1, ldrFileSize); memcpy(section[0].address + ldrOffset + ldrFileSize, arm11SysMods + ldrOffset + ldrInFirmSize, section[0].size - (ldrOffset + ldrInFirmSize)); fclose(); //Dont boot emu if AGB game was just played, or if START was held. getEmunandSect(&emuOffset, &emuHeader); if((HID & 0xFFF) == (1 << 3) || CFG_BOOTENV == 0x7 || !(emuOffset | emuHeader)) loadSys(); else loadEmu(); }
//Nand redirection void loadEmu(void){ //Read emunand code from SD u32 code = emuCode(); const char path[] = "/rei/emunand/emunand.bin"; u32 size = fileSize(path); fileRead(code, path, size); //Find and patch emunand related offsets u32 *pos_sdmmc = memsearch(code, "SDMC", size, 4); u32 *pos_offset = memsearch(code, "NAND", size, 4); u32 *pos_header = memsearch(code, "NCSD", size, 4); getSDMMC(firmLocation, &sdmmcOffset, firmSize); getEmunandSect(&emuOffset, &emuHeader); getEmuRW(firmLocation, firmSize, &emuRead, &emuWrite); *pos_sdmmc = sdmmcOffset; *pos_offset = emuOffset; *pos_header = emuHeader; //Add emunand hooks memcpy((u8*)emuRead, nandRedir, sizeof(nandRedir)); memcpy((u8*)emuWrite, nandRedir, sizeof(nandRedir)); memcpy((u8*)mpuCode(), mpu, sizeof(mpu)); }