From e2c799ca5db370744c4e71904eb50198b3f28e85 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Mon, 20 Feb 2017 19:58:36 +0100 Subject: [PATCH] Allow setting up a bonus drive on unused space --- source/common/common.h | 2 +- source/fatfs/diskio.c | 74 ++++++++++++++++++++---------------------- source/fatfs/ffconf.h | 2 +- source/fs/fsdrive.c | 11 ++++--- source/fs/fsdrive.h | 5 +-- source/fs/fsutil.c | 13 ++++++++ source/fs/fsutil.h | 3 ++ source/godmode.c | 12 +++++-- 8 files changed, 73 insertions(+), 49 deletions(-) diff --git a/source/common/common.h b/source/common/common.h index f78be21..e3550ab 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -38,7 +38,7 @@ (((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v)) // GodMode9 version -#define VERSION "0.9.9.2" +#define VERSION "0.9.9.3" // input / output paths #define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9" diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 7e59431..370db3a 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -13,20 +13,28 @@ #include "nand.h" #include "sdmmc.h" + +#define FPDRV(pdrv) (((pdrv >= 7) && !nand_type_img) ? pdrv + 3 : pdrv) +#define PART_TYPE(pdrv) (DriveInfo[FPDRV(pdrv)].type) +#define PART_SUBTYPE(pdrv) (DriveInfo[FPDRV(pdrv)].subtype) +#define NAND_TYPE(type) ((type == TYPE_SYSNAND) ? nand_type_sys : (type == TYPE_EMUNAND) ? nand_type_emu : (type == TYPE_IMGNAND) ? nand_type_img : 0) + #define TYPE_NONE 0 #define TYPE_SYSNAND NAND_SYSNAND #define TYPE_EMUNAND NAND_EMUNAND #define TYPE_IMGNAND NAND_IMGNAND -#define TYPE_SDCARD (1<<4) -#define TYPE_IMAGE (1<<5) -#define TYPE_RAMDRV (1<<6) +#define TYPE_SDCARD (1UL<<4) +#define TYPE_IMAGE (1UL<<5) +#define TYPE_RAMDRV (1UL<<6) #define SUBTYPE_CTRN 0 #define SUBTYPE_CTRN_N 1 #define SUBTYPE_CTRN_NO 2 #define SUBTYPE_TWLN 3 #define SUBTYPE_TWLP 4 -#define SUBTYPE_NONE 5 +#define SUBTYPE_FREE 5 +#define SUBTYPE_FREE_N 6 +#define SUBTYPE_NONE 7 typedef struct { BYTE type; @@ -39,7 +47,7 @@ typedef struct { BYTE keyslot; } SubtypeDesc; -FATpartition DriveInfo[12] = { +FATpartition DriveInfo[13] = { { TYPE_SDCARD, SUBTYPE_NONE }, // 0 - SDCARD { TYPE_SYSNAND, SUBTYPE_CTRN }, // 1 - SYSNAND CTRNAND { TYPE_SYSNAND, SUBTYPE_TWLN }, // 2 - SYSNAND TWLN @@ -51,15 +59,18 @@ FATpartition DriveInfo[12] = { { TYPE_IMGNAND, SUBTYPE_TWLN }, // 8 - IMGNAND TWLN { TYPE_IMGNAND, SUBTYPE_TWLP }, // 9 - IMGNAND TWLP { TYPE_IMAGE, SUBTYPE_NONE }, // X - IMAGE - { TYPE_RAMDRV, SUBTYPE_NONE } // Y - RAMDRIVE + { TYPE_SYSNAND, SUBTYPE_FREE }, // Y - SYSNAND BONUS + { TYPE_RAMDRV, SUBTYPE_NONE } // Z - RAMDRIVE }; -SubtypeDesc SubTypes[5] = { - { 0x05C980, 0x17AE80, 0x4 }, // O3DS CTRNAND - { 0x05C980, 0x20F680, 0x5 }, // N3DS CTRNAND - { 0x05C980, 0x20F680, 0x4 }, // N3DS CTRNAND (downgraded) - { 0x000097, 0x047DA9, 0x3 }, // TWLN - { 0x04808D, 0x0105B3, 0x3 } // TWLP +SubtypeDesc SubTypes[7] = { + { 0x05C980, 0x17AE80, 0x04 }, // O3DS CTRNAND + { 0x05C980, 0x20F680, 0x05 }, // N3DS CTRNAND + { 0x05C980, 0x20F680, 0x04 }, // N3DS CTRNAND (downgraded) + { 0x000097, 0x047DA9, 0x03 }, // TWLN + { 0x04808D, 0x0105B3, 0x03 }, // TWLP + { 0x1D7800, 0x000000, 0xFF }, // O3DS FREE SPACE + { 0x26C000, 0x000000, 0xFF } // N3DS FREE SPACE }; static BYTE nand_type_sys = 0; @@ -68,22 +79,6 @@ static BYTE nand_type_img = 0; -/*-----------------------------------------------------------------------*/ -/* Get actual FAT partition type helper */ -/*-----------------------------------------------------------------------*/ - -static inline BYTE get_partition_type( - __attribute__((unused)) - BYTE pdrv /* Physical drive number to identify the drive */ -) -{ - if ((pdrv >= 7) && !nand_type_img) // special handling for FAT images - return (pdrv == 7) ? TYPE_IMAGE : (pdrv == 9) ? TYPE_RAMDRV : TYPE_NONE; - return DriveInfo[pdrv].type; -} - - - /*-----------------------------------------------------------------------*/ /* Get Drive Subtype helper */ /*-----------------------------------------------------------------------*/ @@ -93,15 +88,16 @@ static inline SubtypeDesc* get_subtype_desc( BYTE pdrv /* Physical drive number to identify the drive */ ) { - BYTE type = get_partition_type(pdrv); - BYTE subtype = (type) ? DriveInfo[pdrv].subtype : SUBTYPE_NONE; + BYTE type = PART_TYPE(pdrv); + BYTE subtype = PART_SUBTYPE(pdrv); + BYTE nand_type = NAND_TYPE(type); if (subtype == SUBTYPE_NONE) { return NULL; - } else if (subtype == SUBTYPE_CTRN) { - BYTE nand_type = (type == TYPE_SYSNAND) ? nand_type_sys : (type == TYPE_EMUNAND) ? nand_type_emu : nand_type_img; - if (nand_type != NAND_TYPE_O3DS) - subtype = (nand_type == NAND_TYPE_N3DS) ? SUBTYPE_CTRN_N : SUBTYPE_CTRN_NO; + } else if ((subtype == SUBTYPE_CTRN) && (nand_type != NAND_TYPE_O3DS)) { + subtype = (nand_type == NAND_TYPE_N3DS) ? SUBTYPE_CTRN_N : SUBTYPE_CTRN_NO; + } else if ((subtype == SUBTYPE_FREE) && (nand_type != NAND_TYPE_O3DS)) { + subtype = SUBTYPE_FREE_N; } return &(SubTypes[subtype]); @@ -146,7 +142,7 @@ DSTATUS disk_initialize ( nand_type_img = (mount_state & IMG_NAND) ? CheckNandType(NAND_IMGNAND) : 0; if (!nand_type_img) { if ((pdrv == 7) && !(mount_state & IMG_FAT)) return STA_NOINIT|STA_NODISK; - else if (pdrv == 8) return STA_NOINIT|STA_NODISK; + else if ((pdrv == 8) && !CheckNandType(NAND_SYSNAND)) return STA_NOINIT|STA_NODISK; else if (pdrv == 9) InitRamDrive(); } } @@ -167,7 +163,7 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); if (type == TYPE_NONE) { return RES_PARERR; @@ -207,7 +203,7 @@ DRESULT disk_write ( UINT count /* Number of sectors to write */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); if (type == TYPE_NONE) { return RES_PARERR; @@ -249,7 +245,7 @@ DRESULT disk_ioctl ( void *buff /* Buffer to send/receive control data */ ) { - BYTE type = get_partition_type(pdrv); + BYTE type = PART_TYPE(pdrv); switch (cmd) { case GET_SECTOR_SIZE: @@ -262,6 +258,8 @@ DRESULT disk_ioctl ( *((DWORD*) buff) = GetMountSize() / 0x200; } else if (type == TYPE_RAMDRV) { // RAM drive *((DWORD*) buff) = GetRamDriveSize() / 0x200; + } else if ((type == TYPE_SYSNAND) && (PART_SUBTYPE(pdrv) == SUBTYPE_FREE)) { // SysNAND free area + *((DWORD*) buff) = getMMCDevice(0)->total_size - get_subtype_desc(pdrv)->offset; } else if (type != TYPE_NONE) { // NAND *((DWORD*) buff) = get_subtype_desc(pdrv)->size; } diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index e1f75e6..af22871 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -51,7 +51,7 @@ /* This option switches f_expand function. (0:Disable or 1:Enable) */ -#define _USE_CHMOD 0 +#define _USE_CHMOD 1 /* This option switches attribute manipulation functions, f_chmod() and f_utime(). / (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */ diff --git a/source/fs/fsdrive.c b/source/fs/fsdrive.c index d129efe..a07ed2a 100644 --- a/source/fs/fsdrive.c +++ b/source/fs/fsdrive.c @@ -21,6 +21,8 @@ int DriveType(const char* path) { } else if ((pdrv >= 0) && (pdrv < NORM_FS)) { if (pdrv == 0) { type = DRV_FAT | DRV_SDCARD | DRV_STDFAT; + } else if ((pdrv == 8) && !(GetMountState() & IMG_NAND)) { + type = DRV_FAT | DRV_SYSNAND | DRV_BONUS | DRV_STDFAT; } else if ((pdrv == 9) && !(GetMountState() & IMG_NAND)) { type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT; } else if (pdrv == 1) { @@ -77,10 +79,11 @@ bool GetRootDirContentsWorker(DirStruct* contents) { if (!DriveType(drvnum[i])) continue; // drive not available memset(entry->path, 0x00, 64); snprintf(entry->path + 0, 4, drvnum[i]); - if ((*(drvnum[i]) == '7') && (GetMountState() & IMG_FAT)) // FAT image handling - snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], "FAT IMAGE"); - else if ((*(drvnum[i]) == '9') && !(GetMountState() & IMG_NAND)) // RAM drive handling - snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], "RAMDRIVE"); + if ((*(drvnum[i]) >= '7') && (*(drvnum[i]) <= '9') && !(GetMountState() & IMG_NAND)) // Drive 7...9 handling + snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], + (*(drvnum[i]) == '7') ? "FAT IMAGE" : + (*(drvnum[i]) == '8') ? "BONUS DRIVE" : + (*(drvnum[i]) == '9') ? "RAMDRIVE" : "UNK"); else if (*(drvnum[i]) == 'G') // Game drive special handling snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[i], (GetMountState() & GAME_CIA ) ? "CIA" : diff --git a/source/fs/fsdrive.h b/source/fs/fsdrive.h index 98ec008..8cfc19a 100644 --- a/source/fs/fsdrive.h +++ b/source/fs/fsdrive.h @@ -24,8 +24,9 @@ #define DRV_GAME (1UL<<11) #define DRV_CART (1UL<<12) #define DRV_ALIAS (1UL<<13) -#define DRV_SEARCH (1UL<<14) -#define DRV_STDFAT (1UL<<15) // standard FAT drive without limitations +#define DRV_BONUS (1UL<<14) +#define DRV_SEARCH (1UL<<15) +#define DRV_STDFAT (1UL<<16) // standard FAT drive without limitations #define FS_DRVNAME \ "SDCARD", \ diff --git a/source/fs/fsutil.c b/source/fs/fsutil.c index 1201360..aa0c569 100644 --- a/source/fs/fsutil.c +++ b/source/fs/fsutil.c @@ -77,6 +77,19 @@ bool FormatSDCard(u64 hidden_mb, u32 cluster_size, const char* label) { return ret; } +bool SetupBonusDrive(void) { + if (!ShowUnlockSequence(3, "Format the bonus drive?\nThis will irreversibly delete\nALL data on it.\n")) + return false; + ShowString("Formatting drive, please wait..."); + if (GetMountState() & IMG_NAND) InitImgFS(NULL); + bool ret = (f_mkfs("8:", FM_ANY, 0, MAIN_BUFFER, MAIN_BUFFER_SIZE) == FR_OK); + if (ret) { + f_setlabel("8:BONUS"); + InitExtFS(); + } + return ret; +} + bool FileUnlock(const char* path) { FIL file; if (!(DriveType(path) & DRV_FAT)) return true; // can't really check this diff --git a/source/fs/fsutil.h b/source/fs/fsutil.h index 8a6257c..f9267dc 100644 --- a/source/fs/fsutil.h +++ b/source/fs/fsutil.h @@ -17,6 +17,9 @@ uint64_t GetSDCardSize(); /** Format the SD card **/ bool FormatSDCard(u64 hidden_mb, u32 cluster_size, const char* label); +/** Format the bonus drive area **/ +bool SetupBonusDrive(void); + /** Check for file lock, offer to unlock if possible **/ bool FileUnlock(const char* path); diff --git a/source/godmode.c b/source/godmode.c index 5245a9a..dae1275 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -1355,8 +1355,8 @@ 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", "Switch EmuNAND" }; - u32 user_select = ShowSelectPrompt(CheckMultiEmuNand() ? 4 : 3, optionstr, + const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu", "Bonus drive setup", "Switch EmuNAND" }; + u32 user_select = ShowSelectPrompt(CheckMultiEmuNand() ? 5 : 4, optionstr, "HOME button pressed.\nSelect action:" ); if (user_select == 1) { exit_mode = GODMODE_EXIT_POWEROFF; @@ -1378,7 +1378,13 @@ u32 GodMode() { InitEmuNandBase(true); InitExtFS(); GetDirContents(current_dir, current_path); - } else if (user_select == 4) { // switch EmuNAND offset + } else if (user_select == 4) { // setup bonus drive + if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_BONUS|DRV_IMAGE))) + clipboard->n_entries = 0; // remove bonus drive clipboard entries + if (!SetupBonusDrive()) ShowPrompt(false, "Setup failed!"); + ClearScreenF(true, true, COLOR_STD_BG); + GetDirContents(current_dir, current_path); + } else if (user_select == 5) { // 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