Persistent RAMdrive, not coupled to image handling

This commit is contained in:
d0k3 2016-12-13 16:00:14 +01:00
parent 236e037229
commit 3b60fe2332
10 changed files with 93 additions and 83 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.8.6" #define VERSION "0.8.7"
// input / output paths // input / output paths
#define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9" #define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9"

View File

@ -9,6 +9,7 @@
#include "diskio.h" /* FatFs lower layer API */ #include "diskio.h" /* FatFs lower layer API */
#include "image.h" #include "image.h"
#include "ramdrive.h"
#include "nand.h" #include "nand.h"
#include "sdmmc.h" #include "sdmmc.h"
@ -18,6 +19,7 @@
#define TYPE_IMGNAND NAND_IMGNAND #define TYPE_IMGNAND NAND_IMGNAND
#define TYPE_SDCARD (1<<4) #define TYPE_SDCARD (1<<4)
#define TYPE_IMAGE (1<<5) #define TYPE_IMAGE (1<<5)
#define TYPE_RAMDRV (1<<6)
#define SUBTYPE_CTRN 0 #define SUBTYPE_CTRN 0
#define SUBTYPE_CTRN_N 1 #define SUBTYPE_CTRN_N 1
@ -37,7 +39,7 @@ typedef struct {
BYTE keyslot; BYTE keyslot;
} SubtypeDesc; } SubtypeDesc;
FATpartition DriveInfo[11] = { FATpartition DriveInfo[12] = {
{ 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
@ -48,7 +50,8 @@ FATpartition DriveInfo[11] = {
{ TYPE_IMGNAND, SUBTYPE_CTRN }, // 7 - IMGNAND CTRNAND { TYPE_IMGNAND, SUBTYPE_CTRN }, // 7 - IMGNAND CTRNAND
{ 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
}; };
SubtypeDesc SubTypes[5] = { SubtypeDesc SubTypes[5] = {
@ -75,7 +78,7 @@ static inline BYTE get_partition_type(
) )
{ {
if ((pdrv >= 7) && !nand_type_img) // special handling for FAT images if ((pdrv >= 7) && !nand_type_img) // special handling for FAT images
return (pdrv == 7) ? TYPE_IMAGE : TYPE_NONE; return (pdrv == 7) ? TYPE_IMAGE : (pdrv == 9) ? TYPE_RAMDRV : TYPE_NONE;
return DriveInfo[pdrv].type; return DriveInfo[pdrv].type;
} }
@ -140,10 +143,12 @@ DSTATUS disk_initialize (
if (!nand_type_emu) return STA_NOINIT|STA_NODISK; if (!nand_type_emu) return STA_NOINIT|STA_NODISK;
} else if (pdrv < 10) { } else if (pdrv < 10) {
UINT mount_state = GetMountState(); UINT mount_state = GetMountState();
if ((mount_state != IMG_NAND) && (mount_state != IMG_FAT) && (mount_state != IMG_RAMDRV)) nand_type_img = (mount_state == IMG_NAND) ? CheckNandType(NAND_IMGNAND) : 0;
return STA_NOINIT|STA_NODISK; if (!nand_type_img) {
nand_type_img = CheckNandType(NAND_IMGNAND); if ((pdrv == 7) && (mount_state != IMG_FAT)) return STA_NOINIT|STA_NODISK;
if ((!nand_type_img) && (pdrv != 7)) return STA_NOINIT|STA_NODISK; else if (pdrv == 8) return STA_NOINIT|STA_NODISK;
else if (pdrv == 9) InitRamDrive();
}
} }
return RES_OK; return RES_OK;
} }
@ -172,6 +177,9 @@ DRESULT disk_read (
} else if (type == TYPE_IMAGE) { } else if (type == TYPE_IMAGE) {
if (ReadImageSectors(buff, sector, count)) if (ReadImageSectors(buff, sector, count))
return RES_PARERR; return RES_PARERR;
} else if (type == TYPE_RAMDRV) {
if (ReadRamDriveSectors(buff, sector, count))
return RES_PARERR;
} else { } else {
SubtypeDesc* subtype = get_subtype_desc(pdrv); SubtypeDesc* subtype = get_subtype_desc(pdrv);
BYTE keyslot = subtype->keyslot; BYTE keyslot = subtype->keyslot;
@ -209,6 +217,9 @@ DRESULT disk_write (
} else if (type == TYPE_IMAGE) { } else if (type == TYPE_IMAGE) {
if (WriteImageSectors(buff, sector, count)) if (WriteImageSectors(buff, sector, count))
return RES_PARERR; return RES_PARERR;
} else if (type == TYPE_RAMDRV) {
if (WriteRamDriveSectors(buff, sector, count))
return RES_PARERR;
} else { } else {
SubtypeDesc* subtype = get_subtype_desc(pdrv); SubtypeDesc* subtype = get_subtype_desc(pdrv);
BYTE keyslot = subtype->keyslot; BYTE keyslot = subtype->keyslot;
@ -249,12 +260,14 @@ DRESULT disk_ioctl (
*((DWORD*) buff) = getMMCDevice(1)->total_size; *((DWORD*) buff) = getMMCDevice(1)->total_size;
} else if (type == TYPE_IMAGE) { // FAT image } else if (type == TYPE_IMAGE) { // FAT image
*((DWORD*) buff) = GetMountSize() / 0x200; *((DWORD*) buff) = GetMountSize() / 0x200;
} else if (type == TYPE_RAMDRV) { // RAM drive
*((DWORD*) buff) = GetRamDriveSize() / 0x200;
} 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;
} }
return RES_OK; return RES_OK;
case GET_BLOCK_SIZE: case GET_BLOCK_SIZE:
*((DWORD*) buff) = (type == TYPE_IMAGE) ? 0x1 : 0x2000; *((DWORD*) buff) = ((type == TYPE_IMAGE) || (type == TYPE_RAMDRV)) ? 0x1 : 0x2000;
return RES_OK; return RES_OK;
case CTRL_SYNC: case CTRL_SYNC:
if ((type == TYPE_IMAGE) || (type == TYPE_IMGNAND)) if ((type == TYPE_IMAGE) || (type == TYPE_IMGNAND))

View File

@ -1,11 +1,7 @@
#include "image.h" #include "image.h"
#include "sddata.h" #include "sddata.h"
#include "platform.h"
#include "ff.h" #include "ff.h"
static u8* ramdrv_buffer = NULL;
static u32 ramdrv_size = 0;
static FIL mount_file; static FIL mount_file;
static u32 mount_state = 0; static u32 mount_state = 0;
@ -16,11 +12,6 @@ int ReadImageBytes(u8* buffer, u64 offset, u64 count) {
UINT bytes_read; UINT bytes_read;
UINT ret; UINT ret;
if (!count) return -1; if (!count) return -1;
if (mount_state == IMG_RAMDRV) {
if ((offset + count) > ramdrv_size) return -1;
memcpy(buffer, ramdrv_buffer + (offset), count);
return 0;
}
if (!mount_state) return FR_INVALID_OBJECT; if (!mount_state) return FR_INVALID_OBJECT;
if (f_tell(&mount_file) != offset) { if (f_tell(&mount_file) != offset) {
if (f_size(&mount_file) < offset) return -1; if (f_size(&mount_file) < offset) return -1;
@ -34,11 +25,6 @@ int WriteImageBytes(const u8* buffer, u64 offset, u64 count) {
UINT bytes_written; UINT bytes_written;
UINT ret; UINT ret;
if (!count) return -1; if (!count) return -1;
if (mount_state == IMG_RAMDRV) {
if ((offset + count) > ramdrv_size) return -1;
memcpy(ramdrv_buffer + (offset), buffer, count);
return 0;
}
if (!mount_state) return FR_INVALID_OBJECT; if (!mount_state) return FR_INVALID_OBJECT;
if (f_tell(&mount_file) != offset) if (f_tell(&mount_file) != offset)
f_lseek(&mount_file, offset); f_lseek(&mount_file, offset);
@ -55,13 +41,11 @@ int WriteImageSectors(const u8* buffer, u32 sector, u32 count) {
} }
int SyncImage(void) { int SyncImage(void) {
return (mount_state == IMG_RAMDRV) ? FR_OK : return mount_state ? f_sync(&mount_file) : FR_INVALID_OBJECT;
mount_state ? f_sync(&mount_file) : FR_INVALID_OBJECT;
} }
u64 GetMountSize(void) { u64 GetMountSize(void) {
return (mount_state == IMG_RAMDRV) ? ramdrv_size : return mount_state ? f_size(&mount_file) : 0;
mount_state ? f_size(&mount_file) : 0;
} }
u32 GetMountState(void) { u32 GetMountState(void) {
@ -72,24 +56,10 @@ const char* GetMountPath(void) {
return mount_path; return mount_path;
} }
u32 MountRamDrive(void) {
if (mount_state && (mount_state != IMG_RAMDRV))
fx_close(&mount_file);
if (GetUnitPlatform() == PLATFORM_3DS) {
ramdrv_buffer = RAMDRV_BUFFER_O3DS;
ramdrv_size = RAMDRV_SIZE_O3DS;
} else {
ramdrv_buffer = RAMDRV_BUFFER_N3DS;
ramdrv_size = RAMDRV_SIZE_N3DS;
}
*mount_path = 0;
return (mount_state = IMG_RAMDRV);
}
u32 MountImage(const char* path) { u32 MountImage(const char* path) {
u32 type = (path) ? IdentifyFileType(path) : 0; u32 type = (path) ? IdentifyFileType(path) : 0;
if (mount_state) { if (mount_state) {
if (mount_state != IMG_RAMDRV) fx_close(&mount_file); fx_close(&mount_file);
mount_state = 0; mount_state = 0;
*mount_path = 0; *mount_path = 0;
} }

View File

@ -3,8 +3,6 @@
#include "common.h" #include "common.h"
#include "filetype.h" #include "filetype.h"
#define IMG_RAMDRV 100 // just so there are no conflicts with file type defines
int ReadImageBytes(u8* buffer, u64 offset, u64 count); int ReadImageBytes(u8* buffer, u64 offset, u64 count);
int WriteImageBytes(const u8* buffer, u64 offset, u64 count); int WriteImageBytes(const u8* buffer, u64 offset, u64 count);
int ReadImageSectors(u8* buffer, u32 sector, u32 count); int ReadImageSectors(u8* buffer, u32 sector, u32 count);
@ -14,5 +12,4 @@ int SyncImage(void);
u64 GetMountSize(void); u64 GetMountSize(void);
u32 GetMountState(void); u32 GetMountState(void);
const char* GetMountPath(void); const char* GetMountPath(void);
u32 MountRamDrive(void);
u32 MountImage(const char* path); u32 MountImage(const char* path);

36
source/fatfs/ramdrive.c Normal file
View File

@ -0,0 +1,36 @@
#include "ramdrive.h"
#include "platform.h"
static u8* ramdrv_buffer = NULL;
static u32 ramdrv_size = 0;
int ReadRamDriveSectors(u8* buffer, u32 sector, u32 count) {
u64 offset = sector * 0x200;
u64 btr = count * 0x200;
if (!ramdrv_buffer) return -1;
if ((offset + btr) > ramdrv_size) return -1;
memcpy(buffer, ramdrv_buffer + offset, btr);
return 0;
}
int WriteRamDriveSectors(const u8* buffer, u32 sector, u32 count) {
u64 offset = sector * 0x200;
u64 btw = count * 0x200;
if (!ramdrv_buffer) return -1;
if ((offset + btw) > ramdrv_size) return -1;
memcpy(ramdrv_buffer + offset, buffer, btw);
return 0;
}
u64 GetRamDriveSize(void) {
return ramdrv_size;
}
void InitRamDrive(void) {
if (GetUnitPlatform() == PLATFORM_3DS) {
ramdrv_buffer = RAMDRV_BUFFER_O3DS;
ramdrv_size = RAMDRV_SIZE_O3DS;
} else {
ramdrv_buffer = RAMDRV_BUFFER_N3DS;
ramdrv_size = RAMDRV_SIZE_N3DS;
}
}

8
source/fatfs/ramdrive.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
#include "common.h"
int ReadRamDriveSectors(u8* buffer, u32 sector, u32 count);
int WriteRamDriveSectors(const u8* buffer, u32 sector, u32 count);
u64 GetRamDriveSize(void);
void InitRamDrive(void);

View File

@ -21,7 +21,7 @@ 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 == 7) && (GetMountState() == IMG_RAMDRV)) { } 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) && (pdrv <= 3)) { } else if ((pdrv >= 1) && (pdrv <= 3)) {
type = DRV_FAT | DRV_SYSNAND | DRV_STDFAT; type = DRV_FAT | DRV_SYSNAND | DRV_STDFAT;
@ -69,9 +69,10 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
if (!DriveType(drvnum[pdrv])) continue; // drive not available if (!DriveType(drvnum[pdrv])) continue; // drive not available
memset(entry->path, 0x00, 64); memset(entry->path, 0x00, 64);
snprintf(entry->path + 0, 4, drvnum[pdrv]); snprintf(entry->path + 0, 4, drvnum[pdrv]);
if ((pdrv == 7) && ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_RAMDRV))) if ((pdrv == 7) && (GetMountState() == IMG_FAT)) // FAT image handling
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], // FAT image / RAM drive special handling snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], "FAT IMAGE");
(GetMountState() == IMG_FAT) ? "FAT IMAGE" : "RAMDRIVE"); else if ((pdrv == 9) && (GetMountState() != IMG_NAND)) // RAM drive handling
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], "RAMDRIVE");
else if (pdrv == 10) // Game drive special handling else if (pdrv == 10) // Game drive special handling
snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv], snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv],
(GetMountState() == GAME_CIA ) ? "CIA" : (GetMountState() == GAME_CIA ) ? "CIA" :

View File

@ -25,6 +25,11 @@ bool InitExtFS() {
snprintf(fsname, 7, "%lu:", i); snprintf(fsname, 7, "%lu:", i);
if (fs_mounted[i]) continue; if (fs_mounted[i]) continue;
fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK);
if (!fs_mounted[i] && (i == NORM_FS - 1) && (GetMountState() != IMG_NAND)) {
f_mkfs(fsname, FM_ANY, 0, MAIN_BUFFER, MAIN_BUFFER_SIZE); // format ramdrive if required
f_mount(NULL, fsname, 1);
fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK);
}
} }
SetupNandSdDrive("A:", "0:", "1:/private/movable.sed", 0); SetupNandSdDrive("A:", "0:", "1:/private/movable.sed", 0);
SetupNandSdDrive("B:", "0:", "4:/private/movable.sed", 1); SetupNandSdDrive("B:", "0:", "4:/private/movable.sed", 1);
@ -53,23 +58,6 @@ bool InitImgFS(const char* path) {
return true; return true;
} }
bool InitRamDriveFS() {
u32 pdrv = NORM_FS - IMGN_FS;
char fsname[8];
snprintf(fsname, 7, "%lu:", pdrv);
InitImgFS(NULL);
MountRamDrive();
fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK);
if (!fs_mounted[pdrv] && (GetMountState() == IMG_RAMDRV)) {
f_mkfs(fsname, FM_ANY, 0, MAIN_BUFFER, MAIN_BUFFER_SIZE); // format ramdrive if required
f_mount(NULL, fsname, 1);
fs_mounted[pdrv] = (f_mount(fs + pdrv, fsname, 1) == FR_OK);
}
return true;
}
void DeinitExtFS() { void DeinitExtFS() {
SetupNandSdDrive(NULL, NULL, NULL, 0); SetupNandSdDrive(NULL, NULL, NULL, 0);
SetupNandSdDrive(NULL, NULL, NULL, 1); SetupNandSdDrive(NULL, NULL, NULL, 1);
@ -80,7 +68,7 @@ void DeinitExtFS() {
f_mount(NULL, fsname, 1); f_mount(NULL, fsname, 1);
fs_mounted[i] = false; fs_mounted[i] = false;
} }
if ((i == NORM_FS - IMGN_FS) && (GetMountState() != IMG_RAMDRV)) { // unmount image if (i == NORM_FS - IMGN_FS) { // unmount image
MountImage(NULL); MountImage(NULL);
InitVGameDrive(); InitVGameDrive();
} }
@ -88,10 +76,8 @@ void DeinitExtFS() {
} }
void DeinitSDCardFS() { void DeinitSDCardFS() {
if (GetMountState() != IMG_RAMDRV) { MountImage(NULL);
MountImage(NULL); InitVGameDrive();
InitVGameDrive();
}
if (fs_mounted[0]) { if (fs_mounted[0]) {
f_mount(NULL, "0:", 1); f_mount(NULL, "0:", 1);
fs_mounted[0] = false; fs_mounted[0] = false;

View File

@ -12,9 +12,6 @@ bool InitExtFS();
// mount and init image file system // mount and init image file system
bool InitImgFS(const char* path); bool InitImgFS(const char* path);
// init RAM drive filesystem (unmounts image)
bool InitRamDriveFS();
// deinitialize external filesystem // deinitialize external filesystem
void DeinitExtFS(); void DeinitExtFS();

View File

@ -139,8 +139,7 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c
"L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - PASTE file(s) / [+R] CREATE dir\n") : "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - PASTE file(s) / [+R] CREATE dir\n") :
((GetWritePermissions() > PERM_BASE) ? "R+Y - Relock write permissions\nR+B - Unmount SD card\n" : ((GetWritePermissions() > PERM_BASE) ? "R+Y - Relock write permissions\nR+B - Unmount SD card\n" :
"R+Y - Unlock write permissions\nR+B - Unmount SD card\n"), "R+Y - Unlock write permissions\nR+B - Unmount SD card\n"),
(*curr_path) ? "" : ((GetMountState() == IMG_RAMDRV) ? "R+X - Unmount RAM drive\n" : (*curr_path) ? "" : "R+X - Reinit filesystem\n",
(GetMountState()) ? "R+X - Unmount image\n" : "R+X - Mount RAM drive\n"),
(*curr_path) ? "R+A - Search directory\n" : "R+A - Search drive\n", (*curr_path) ? "R+A - Search directory\n" : "R+A - Search drive\n",
"R+L - Make a Screenshot\n", "R+L - Make a Screenshot\n",
"R+\x1B\x1A - Switch to prev/next pane\n", "R+\x1B\x1A - Switch to prev/next pane\n",
@ -652,10 +651,10 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
// auto select when there is only one option // auto select when there is only one option
user_select = (n_opt > 1) ? (int) ShowSelectPrompt(n_opt, optionstr, pathstr) : n_opt; user_select = (n_opt > 1) ? (int) ShowSelectPrompt(n_opt, optionstr, pathstr) : n_opt;
if (user_select == mount) { // -> mount file as image if (user_select == mount) { // -> mount file as image
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_IMAGE|DRV_RAMDRIVE))) if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE))
clipboard->n_entries = 0; // remove last mounted image clipboard entries clipboard->n_entries = 0; // remove last mounted image clipboard entries
InitImgFS(curr_entry->path); InitImgFS(curr_entry->path);
if (!(DriveType("7:")||DriveType("8:")||DriveType("9:")||DriveType("G:"))) { if (!(DriveType("7:")||DriveType("G:"))) {
ShowPrompt(false, "Mounting image: failed"); ShowPrompt(false, "Mounting image: failed");
InitImgFS(NULL); InitImgFS(NULL);
} else { } else {
@ -663,7 +662,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
*current_path = '\0'; *current_path = '\0';
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
for (u32 i = 0; i < current_dir->n_entries; i++) { for (u32 i = 0; i < current_dir->n_entries; i++) {
if (strspn(current_dir->entry[i].path, "789GI") == 0) if (strspn(current_dir->entry[i].path, "7GI") == 0)
continue; continue;
strncpy(current_path, current_dir->entry[i].path, 256); strncpy(current_path, current_dir->entry[i].path, 256);
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
@ -937,11 +936,14 @@ u32 GodMode() {
// highly specific commands // highly specific commands
if (!*current_path) { // in the root folder... if (!*current_path) { // in the root folder...
if (switched && (pad_state & BUTTON_X)) { // unmount image if (switched && (pad_state & BUTTON_X)) { // reinit file system / unmount image
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_IMAGE|DRV_RAMDRIVE))) if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE))
clipboard->n_entries = 0; // remove last mounted image clipboard entries clipboard->n_entries = 0; // remove last mounted image clipboard entries
if (!GetMountState()) InitRamDriveFS(); DeinitExtFS();
else InitImgFS(NULL); DeinitSDCardFS();
InitSDCardFS();
InitExtFS();
ClearScreenF(false, true, COLOR_STD_BG);
GetDirContents(current_dir, current_path); GetDirContents(current_dir, current_path);
} else if (switched && (pad_state & BUTTON_Y)) { } else if (switched && (pad_state & BUTTON_Y)) {
SetWritePermissions((GetWritePermissions() > PERM_BASE) ? PERM_BASE : PERM_ALL, false); SetWritePermissions((GetWritePermissions() > PERM_BASE) ? PERM_BASE : PERM_ALL, false);