Allow setting up a bonus drive on unused space

This commit is contained in:
d0k3 2017-02-20 19:58:36 +01:00
parent 1348b7ca03
commit e2c799ca5d
8 changed files with 73 additions and 49 deletions

View File

@ -38,7 +38,7 @@
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v)) (((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
// GodMode9 version // GodMode9 version
#define VERSION "0.9.9.2" #define VERSION "0.9.9.3"
// input / output paths // input / output paths
#define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9" #define INPUT_PATHS "0:", "0:/files9", "1:/rw/files9"

View File

@ -13,20 +13,28 @@
#include "nand.h" #include "nand.h"
#include "sdmmc.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_NONE 0
#define TYPE_SYSNAND NAND_SYSNAND #define TYPE_SYSNAND NAND_SYSNAND
#define TYPE_EMUNAND NAND_EMUNAND #define TYPE_EMUNAND NAND_EMUNAND
#define TYPE_IMGNAND NAND_IMGNAND #define TYPE_IMGNAND NAND_IMGNAND
#define TYPE_SDCARD (1<<4) #define TYPE_SDCARD (1UL<<4)
#define TYPE_IMAGE (1<<5) #define TYPE_IMAGE (1UL<<5)
#define TYPE_RAMDRV (1<<6) #define TYPE_RAMDRV (1UL<<6)
#define SUBTYPE_CTRN 0 #define SUBTYPE_CTRN 0
#define SUBTYPE_CTRN_N 1 #define SUBTYPE_CTRN_N 1
#define SUBTYPE_CTRN_NO 2 #define SUBTYPE_CTRN_NO 2
#define SUBTYPE_TWLN 3 #define SUBTYPE_TWLN 3
#define SUBTYPE_TWLP 4 #define SUBTYPE_TWLP 4
#define SUBTYPE_NONE 5 #define SUBTYPE_FREE 5
#define SUBTYPE_FREE_N 6
#define SUBTYPE_NONE 7
typedef struct { typedef struct {
BYTE type; BYTE type;
@ -39,7 +47,7 @@ typedef struct {
BYTE keyslot; BYTE keyslot;
} SubtypeDesc; } SubtypeDesc;
FATpartition DriveInfo[12] = { FATpartition DriveInfo[13] = {
{ TYPE_SDCARD, SUBTYPE_NONE }, // 0 - SDCARD { TYPE_SDCARD, SUBTYPE_NONE }, // 0 - SDCARD
{ TYPE_SYSNAND, SUBTYPE_CTRN }, // 1 - SYSNAND CTRNAND { TYPE_SYSNAND, SUBTYPE_CTRN }, // 1 - SYSNAND CTRNAND
{ TYPE_SYSNAND, SUBTYPE_TWLN }, // 2 - SYSNAND TWLN { TYPE_SYSNAND, SUBTYPE_TWLN }, // 2 - SYSNAND TWLN
@ -51,15 +59,18 @@ FATpartition DriveInfo[12] = {
{ TYPE_IMGNAND, SUBTYPE_TWLN }, // 8 - IMGNAND TWLN { TYPE_IMGNAND, SUBTYPE_TWLN }, // 8 - IMGNAND TWLN
{ TYPE_IMGNAND, SUBTYPE_TWLP }, // 9 - IMGNAND TWLP { TYPE_IMGNAND, SUBTYPE_TWLP }, // 9 - IMGNAND TWLP
{ TYPE_IMAGE, SUBTYPE_NONE }, // X - IMAGE { 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] = { SubtypeDesc SubTypes[7] = {
{ 0x05C980, 0x17AE80, 0x4 }, // O3DS CTRNAND { 0x05C980, 0x17AE80, 0x04 }, // O3DS CTRNAND
{ 0x05C980, 0x20F680, 0x5 }, // N3DS CTRNAND { 0x05C980, 0x20F680, 0x05 }, // N3DS CTRNAND
{ 0x05C980, 0x20F680, 0x4 }, // N3DS CTRNAND (downgraded) { 0x05C980, 0x20F680, 0x04 }, // N3DS CTRNAND (downgraded)
{ 0x000097, 0x047DA9, 0x3 }, // TWLN { 0x000097, 0x047DA9, 0x03 }, // TWLN
{ 0x04808D, 0x0105B3, 0x3 } // TWLP { 0x04808D, 0x0105B3, 0x03 }, // TWLP
{ 0x1D7800, 0x000000, 0xFF }, // O3DS FREE SPACE
{ 0x26C000, 0x000000, 0xFF } // N3DS FREE SPACE
}; };
static BYTE nand_type_sys = 0; 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 */ /* Get Drive Subtype helper */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
@ -93,15 +88,16 @@ static inline SubtypeDesc* get_subtype_desc(
BYTE pdrv /* Physical drive number to identify the drive */ BYTE pdrv /* Physical drive number to identify the drive */
) )
{ {
BYTE type = get_partition_type(pdrv); BYTE type = PART_TYPE(pdrv);
BYTE subtype = (type) ? DriveInfo[pdrv].subtype : SUBTYPE_NONE; BYTE subtype = PART_SUBTYPE(pdrv);
BYTE nand_type = NAND_TYPE(type);
if (subtype == SUBTYPE_NONE) { if (subtype == SUBTYPE_NONE) {
return NULL; return NULL;
} else if (subtype == SUBTYPE_CTRN) { } else if ((subtype == SUBTYPE_CTRN) && (nand_type != NAND_TYPE_O3DS)) {
BYTE nand_type = (type == TYPE_SYSNAND) ? nand_type_sys : (type == TYPE_EMUNAND) ? nand_type_emu : nand_type_img; subtype = (nand_type == NAND_TYPE_N3DS) ? SUBTYPE_CTRN_N : SUBTYPE_CTRN_NO;
if (nand_type != NAND_TYPE_O3DS) } else if ((subtype == SUBTYPE_FREE) && (nand_type != NAND_TYPE_O3DS)) {
subtype = (nand_type == NAND_TYPE_N3DS) ? SUBTYPE_CTRN_N : SUBTYPE_CTRN_NO; subtype = SUBTYPE_FREE_N;
} }
return &(SubTypes[subtype]); return &(SubTypes[subtype]);
@ -146,7 +142,7 @@ DSTATUS disk_initialize (
nand_type_img = (mount_state & IMG_NAND) ? CheckNandType(NAND_IMGNAND) : 0; nand_type_img = (mount_state & IMG_NAND) ? CheckNandType(NAND_IMGNAND) : 0;
if (!nand_type_img) { if (!nand_type_img) {
if ((pdrv == 7) && !(mount_state & IMG_FAT)) return STA_NOINIT|STA_NODISK; 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(); else if (pdrv == 9) InitRamDrive();
} }
} }
@ -167,7 +163,7 @@ DRESULT disk_read (
UINT count /* Number of sectors to read */ UINT count /* Number of sectors to read */
) )
{ {
BYTE type = get_partition_type(pdrv); BYTE type = PART_TYPE(pdrv);
if (type == TYPE_NONE) { if (type == TYPE_NONE) {
return RES_PARERR; return RES_PARERR;
@ -207,7 +203,7 @@ DRESULT disk_write (
UINT count /* Number of sectors to write */ UINT count /* Number of sectors to write */
) )
{ {
BYTE type = get_partition_type(pdrv); BYTE type = PART_TYPE(pdrv);
if (type == TYPE_NONE) { if (type == TYPE_NONE) {
return RES_PARERR; return RES_PARERR;
@ -249,7 +245,7 @@ DRESULT disk_ioctl (
void *buff /* Buffer to send/receive control data */ void *buff /* Buffer to send/receive control data */
) )
{ {
BYTE type = get_partition_type(pdrv); BYTE type = PART_TYPE(pdrv);
switch (cmd) { switch (cmd) {
case GET_SECTOR_SIZE: case GET_SECTOR_SIZE:
@ -262,6 +258,8 @@ DRESULT disk_ioctl (
*((DWORD*) buff) = GetMountSize() / 0x200; *((DWORD*) buff) = GetMountSize() / 0x200;
} else if (type == TYPE_RAMDRV) { // RAM drive } else if (type == TYPE_RAMDRV) { // RAM drive
*((DWORD*) buff) = GetRamDriveSize() / 0x200; *((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 } else if (type != TYPE_NONE) { // NAND
*((DWORD*) buff) = get_subtype_desc(pdrv)->size; *((DWORD*) buff) = get_subtype_desc(pdrv)->size;
} }

View File

@ -51,7 +51,7 @@
/* This option switches f_expand function. (0:Disable or 1:Enable) */ /* 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(). /* 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. */ / (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */

View File

@ -21,6 +21,8 @@ int DriveType(const char* path) {
} else if ((pdrv >= 0) && (pdrv < NORM_FS)) { } else if ((pdrv >= 0) && (pdrv < NORM_FS)) {
if (pdrv == 0) { if (pdrv == 0) {
type = DRV_FAT | DRV_SDCARD | DRV_STDFAT; 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)) { } else if ((pdrv == 9) && !(GetMountState() & IMG_NAND)) {
type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT; type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT;
} else if (pdrv == 1) { } else if (pdrv == 1) {
@ -77,10 +79,11 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
if (!DriveType(drvnum[i])) continue; // drive not available if (!DriveType(drvnum[i])) continue; // drive not available
memset(entry->path, 0x00, 64); memset(entry->path, 0x00, 64);
snprintf(entry->path + 0, 4, drvnum[i]); snprintf(entry->path + 0, 4, drvnum[i]);
if ((*(drvnum[i]) == '7') && (GetMountState() & IMG_FAT)) // FAT image handling if ((*(drvnum[i]) >= '7') && (*(drvnum[i]) <= '9') && !(GetMountState() & IMG_NAND)) // Drive 7...9 handling
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], "FAT IMAGE"); snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i],
else if ((*(drvnum[i]) == '9') && !(GetMountState() & IMG_NAND)) // RAM drive handling (*(drvnum[i]) == '7') ? "FAT IMAGE" :
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[i], "RAMDRIVE"); (*(drvnum[i]) == '8') ? "BONUS DRIVE" :
(*(drvnum[i]) == '9') ? "RAMDRIVE" : "UNK");
else if (*(drvnum[i]) == 'G') // Game drive special handling else if (*(drvnum[i]) == 'G') // Game drive special handling
snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[i], snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[i],
(GetMountState() & GAME_CIA ) ? "CIA" : (GetMountState() & GAME_CIA ) ? "CIA" :

View File

@ -24,8 +24,9 @@
#define DRV_GAME (1UL<<11) #define DRV_GAME (1UL<<11)
#define DRV_CART (1UL<<12) #define DRV_CART (1UL<<12)
#define DRV_ALIAS (1UL<<13) #define DRV_ALIAS (1UL<<13)
#define DRV_SEARCH (1UL<<14) #define DRV_BONUS (1UL<<14)
#define DRV_STDFAT (1UL<<15) // standard FAT drive without limitations #define DRV_SEARCH (1UL<<15)
#define DRV_STDFAT (1UL<<16) // standard FAT drive without limitations
#define FS_DRVNAME \ #define FS_DRVNAME \
"SDCARD", \ "SDCARD", \

View File

@ -77,6 +77,19 @@ bool FormatSDCard(u64 hidden_mb, u32 cluster_size, const char* label) {
return ret; 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) { bool FileUnlock(const char* path) {
FIL file; FIL file;
if (!(DriveType(path) & DRV_FAT)) return true; // can't really check this if (!(DriveType(path) & DRV_FAT)) return true; // can't really check this

View File

@ -17,6 +17,9 @@ uint64_t GetSDCardSize();
/** Format the SD card **/ /** Format the SD card **/
bool FormatSDCard(u64 hidden_mb, u32 cluster_size, const char* label); 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 **/ /** Check for file lock, offer to unlock if possible **/
bool FileUnlock(const char* path); bool FileUnlock(const char* path);

View File

@ -1355,8 +1355,8 @@ u32 GodMode() {
exit_mode = GODMODE_EXIT_POWEROFF; exit_mode = GODMODE_EXIT_POWEROFF;
break; break;
} else if (pad_state & BUTTON_HOME) { // Home menu } else if (pad_state & BUTTON_HOME) { // Home menu
const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu", "Switch EmuNAND" }; const char* optionstr[] = { "Poweroff system", "Reboot system", "SD format menu", "Bonus drive setup", "Switch EmuNAND" };
u32 user_select = ShowSelectPrompt(CheckMultiEmuNand() ? 4 : 3, optionstr, u32 user_select = ShowSelectPrompt(CheckMultiEmuNand() ? 5 : 4, optionstr,
"HOME button pressed.\nSelect action:" ); "HOME button pressed.\nSelect action:" );
if (user_select == 1) { if (user_select == 1) {
exit_mode = GODMODE_EXIT_POWEROFF; exit_mode = GODMODE_EXIT_POWEROFF;
@ -1378,7 +1378,13 @@ u32 GodMode() {
InitEmuNandBase(true); InitEmuNandBase(true);
InitExtFS(); InitExtFS();
GetDirContents(current_dir, current_path); 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())) { while (ShowPrompt(true, "Current EmuNAND offset is %06X.\nSwitch to next offset?", GetEmuNandBase())) {
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_EMUNAND)) if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_EMUNAND))
clipboard->n_entries = 0; // remove SD clipboard entries clipboard->n_entries = 0; // remove SD clipboard entries