diff --git a/source/godmode.c b/source/godmode.c index 9715780..c4d8c82 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -834,7 +834,7 @@ u32 GodMode() { else if (user_select == 5) SdFormatMenu(); ClearScreenF(true, true, COLOR_STD_BG); } - InitEmuNandBase(); + InitEmuNandBase(true); InitNandCrypto(); InitExtFS(); @@ -947,7 +947,7 @@ u32 GodMode() { clipboard->n_entries = 0; // remove SD clipboard entries } ClearScreenF(true, true, COLOR_STD_BG); - InitEmuNandBase(); + InitEmuNandBase(true); InitExtFS(); GetDirContents(current_dir, current_path); if (cursor >= current_dir->n_entries) cursor = 0; @@ -1128,8 +1128,9 @@ u32 GodMode() { exit_mode = GODMODE_EXIT_POWEROFF; break; } else if (pad_state & BUTTON_HOME) { // Home menu - const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu" }; - u32 user_select = ShowSelectPrompt(3, optionstr, "HOME button pressed.\nSelect action:" ); + const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu", "Switch EmuNAND" }; + u32 user_select = ShowSelectPrompt(CheckMultiEmuNand() ? 4 : 3, optionstr, + "HOME button pressed.\nSelect action:" ); if (user_select == 1) { exit_mode = GODMODE_EXIT_POWEROFF; break; @@ -1147,9 +1148,17 @@ u32 GodMode() { ShowPrompt(true, "Reinitialising SD card failed! Retry?")); } ClearScreenF(true, true, COLOR_STD_BG); - InitEmuNandBase(); + InitEmuNandBase(true); InitExtFS(); GetDirContents(current_dir, current_path); + } else if (user_select == 4) { // switch EmuNAND offset + while (ShowPrompt(true, "Current EmuNAND offset is %06X.\nSwitch to next offset?", GetEmuNandBase())) { + if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_EMUNAND)) + clipboard->n_entries = 0; // remove SD clipboard entries + DismountDriveType(DRV_EMUNAND); + InitEmuNandBase(false); + InitExtFS(); + } } } else if ((pad_state & (CART_INSERT|CART_EJECT)) && (curr_drvtype & DRV_CART)) { GetDirContents(current_dir, current_path); // refresh cart dir contents diff --git a/source/nand/nand.c b/source/nand/nand.c index 02408ec..ff3e3db 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -393,10 +393,9 @@ u64 GetNandSizeSectors(u32 nand_src) if (nand_src == NAND_EMUNAND) { // for EmuNAND u32 partition_offset = GetPartitionOffsetSector("0:"); u32 emunand_max_sectors = (partition_offset >= (emunand_base_sector + 1)) ? // +1 for safety - partition_offset - (emunand_base_sector + 1) : 0; - u32 emunand_min_sectors = (emunand_base_sector % 0x200000 == 0) ? sysnand_sectors : NAND_MIN_SECTORS; - if (emunand_max_sectors >= sysnand_sectors) return sysnand_sectors; - else return (emunand_min_sectors > emunand_max_sectors) ? 0 : emunand_min_sectors; + partition_offset - (emunand_base_sector + 1) : 0; + u32 emunand_min_sectors = (emunand_base_sector % 0x2000 == 0) ? sysnand_sectors : NAND_MIN_SECTORS; + return (emunand_min_sectors > emunand_max_sectors) ? 0 : emunand_min_sectors; } else if (nand_src == NAND_IMGNAND) { // for images u32 img_sectors = (GetMountState() == IMG_NAND) ? GetMountSize() / 0x200 : 0; return (img_sectors >= sysnand_sectors) ? sysnand_sectors : (img_sectors >= NAND_MIN_SECTORS) ? NAND_MIN_SECTORS : 0; @@ -407,15 +406,43 @@ u64 GetNandSizeSectors(u32 nand_src) return 0; } -bool InitEmuNandBase(void) +bool CheckMultiEmuNand(void) { - emunand_base_sector = 0x000000; // GW type EmuNAND - if (CheckNandType(NAND_EMUNAND)) - return true; - - emunand_base_sector = 0x000001; // RedNAND type EmuNAND - if (CheckNandType(NAND_EMUNAND)) - return true; - - return false; + // this only checks for the theoretical possibility + return (GetPartitionOffsetSector("0:") >= (u64) (align(NAND_MIN_SECTORS + 1, 0x2000) * 2)); +} + +u32 InitEmuNandBase(bool reset) +{ + if (!reset) { + u32 last_valid = emunand_base_sector; + + // legacy type multiNAND + u32 legacy_sectors = (getMMCDevice(0)->total_size > 0x200000) ? 0x400000 : 0x200000; + emunand_base_sector += legacy_sectors - (emunand_base_sector % legacy_sectors); + if (GetNandSizeSectors(NAND_EMUNAND) && CheckNandType(NAND_EMUNAND)) + return emunand_base_sector; // GW type EmuNAND + emunand_base_sector++; + if (GetNandSizeSectors(NAND_EMUNAND) && CheckNandType(NAND_EMUNAND)) + return emunand_base_sector; // RedNAND type EmuNAND + + // compact type multiNAND + if (last_valid % 0x2000 == 1) { + u32 compact_sectors = align(NAND_MIN_SECTORS + 1, 0x2000); + emunand_base_sector = last_valid + compact_sectors; + if (GetNandSizeSectors(NAND_EMUNAND) && CheckNandType(NAND_EMUNAND)) + return emunand_base_sector; + } + } + + emunand_base_sector = 0x000000; // GW type EmuNAND + if (!CheckNandType(NAND_EMUNAND)) + emunand_base_sector = 0x000001; // RedNAND type EmuNAND + + return emunand_base_sector; +} + +u32 GetEmuNandBase(void) +{ + return emunand_base_sector; } diff --git a/source/nand/nand.h b/source/nand/nand.h index 7cd2ee9..94ad9a4 100644 --- a/source/nand/nand.h +++ b/source/nand/nand.h @@ -50,4 +50,6 @@ u64 GetNandSizeSectors(u32 src); u32 CheckNandHeader(u8* header); u32 CheckNandType(u32 src); -bool InitEmuNandBase(void); +bool CheckMultiEmuNand(void); +u32 InitEmuNandBase(bool reset); +u32 GetEmuNandBase(void);