diff --git a/source/fatfs/ffconf.h b/source/fatfs/ffconf.h index 7512187..d4c0ea6 100644 --- a/source/fatfs/ffconf.h +++ b/source/fatfs/ffconf.h @@ -47,7 +47,7 @@ / f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */ -#define _USE_MKFS 0 +#define _USE_MKFS 1 /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ diff --git a/source/fatfs/image.c b/source/fatfs/image.c index 4584823..8ce2239 100644 --- a/source/fatfs/image.c +++ b/source/fatfs/image.c @@ -1,17 +1,31 @@ #include "image.h" +#include "platform.h" #include "fatfs/ff.h" -FIL mount_file; -u32 mount_state = 0; +#define RAMDRV_BUFFER_O3DS ((u8*)0x22200000) // in O3DS FCRAM +#define RAMDRV_SIZE_O3DS (0x01C00000) // 28MB +#define RAMDRV_BUFFER_N3DS ((u8*)0x28000000) // in N3DS FCRAM +#define RAMDRV_SIZE_N3DS (0x08000000) // 128MB + +static u8* ramdrv_buffer = NULL; +static u32 ramdrv_size = 0; + +static FIL mount_file; +static u32 mount_state = 0; int ReadImageSectors(u8* buffer, u32 sector, u32 count) { UINT bytes_read; UINT ret; if (!count) return -1; + if (mount_state == IMG_RAMDRV) { + if ((sector + count) * 0x200 > ramdrv_size) return -1; + memcpy(buffer, ramdrv_buffer + (sector * 0x200), count * 0x200); + return 0; + } if (!mount_state) return FR_INVALID_OBJECT; if (f_tell(&mount_file) != sector * 0x200) { if (f_size(&mount_file) < sector * 0x200) return -1; - f_lseek(&mount_file, sector * 0x200); + f_lseek(&mount_file, sector * 0x200); } ret = f_read(&mount_file, buffer, count * 0x200, &bytes_read); return (ret != 0) ? (int) ret : (bytes_read != count * 0x200) ? -1 : 0; @@ -21,6 +35,11 @@ int WriteImageSectors(const u8* buffer, u32 sector, u32 count) { UINT bytes_written; UINT ret; if (!count) return -1; + if (mount_state == IMG_RAMDRV) { + if ((sector + count) * 0x200 > ramdrv_size) return -1; + memcpy(ramdrv_buffer + (sector * 0x200), buffer, count * 0x200); + return 0; + } if (!mount_state) return FR_INVALID_OBJECT; if (f_tell(&mount_file) != sector * 0x200) f_lseek(&mount_file, sector * 0x200); @@ -29,11 +48,13 @@ int WriteImageSectors(const u8* buffer, u32 sector, u32 count) { } int SyncImage(void) { - return (mount_state) ? f_sync(&mount_file) : FR_INVALID_OBJECT; + return (mount_state == IMG_RAMDRV) ? FR_OK : + mount_state ? f_sync(&mount_file) : FR_INVALID_OBJECT; } u64 GetMountSize(void) { - return mount_state ? f_size(&mount_file) : 0; + return (mount_state == IMG_RAMDRV) ? ramdrv_size : + mount_state ? f_size(&mount_file) : 0; } u32 GetMountState(void) { @@ -71,9 +92,22 @@ u32 IdentifyImage(const char* path) { return 0; } +u32 MountRamDrive(void) { + if (mount_state && (mount_state != IMG_RAMDRV)) + f_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; + } + return (mount_state = IMG_RAMDRV); +} + u32 MountImage(const char* path) { if (mount_state) { - f_close(&mount_file); + if (mount_state != IMG_RAMDRV) f_close(&mount_file); mount_state = 0; } if (!path || !IdentifyImage(path)) return 0; diff --git a/source/fatfs/image.h b/source/fatfs/image.h index 18dc5cd..98fd196 100644 --- a/source/fatfs/image.h +++ b/source/fatfs/image.h @@ -2,8 +2,9 @@ #include "common.h" -#define IMG_FAT 1 -#define IMG_NAND 2 +#define IMG_FAT 1 +#define IMG_NAND 2 +#define IMG_RAMDRV 3 int ReadImageSectors(u8* buffer, u32 sector, u32 count); int WriteImageSectors(const u8* buffer, u32 sector, u32 count); @@ -12,4 +13,5 @@ int SyncImage(void); u64 GetMountSize(void); u32 GetMountState(void); u32 IdentifyImage(const char* path); +u32 MountRamDrive(void); u32 MountImage(const char* path); diff --git a/source/fs.c b/source/fs.c index d3ff698..af535ed 100644 --- a/source/fs.c +++ b/source/fs.c @@ -36,8 +36,12 @@ bool InitExtFS() { for (u32 i = 1; i < NORM_FS; i++) { char fsname[8]; snprintf(fsname, 7, "%lu:", i); - if (f_mount(fs + i, fsname, 1) == FR_OK) - fs_mounted[i] = true; + fs_mounted[i] = (f_mount(fs + i, fsname, 1) == FR_OK); + if ((i == 7) && !fs_mounted[7] && (GetMountState() == IMG_RAMDRV)) { + f_mkfs("7:", 0, 0); // format ramdrive if required + f_mount(NULL, fsname, 1); + fs_mounted[7] = (f_mount(fs + 7, "7:", 1) == FR_OK); + } } return true; } @@ -82,6 +86,8 @@ bool CheckWritePermissions(const char* path) { (GetVirtualSource(path) == VRT_SYSNAND) ? 1 : (GetVirtualSource(path) == VRT_EMUNAND) ? 4 : 7; else return false; + } else if ((pdrv == 7) && (GetMountState() == IMG_RAMDRV)) { + pdrv = 0; // ...and another hack } if ((pdrv >= 1) && (pdrv <= 3) && (write_permission_level < 3)) { @@ -720,6 +726,8 @@ bool GetRootDirContentsWorker(DirStruct* contents) { snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], drvname[pdrv]); if ((GetMountState() == IMG_FAT) && (pdrv == 7)) // FAT image special handling snprintf(entry->path + 4, 32, "[7:] FAT IMAGE"); + else if ((GetMountState() == IMG_RAMDRV) && (pdrv == 7)) // RAM drive special handling + snprintf(entry->path + 4, 32, "[7:] RAMDRIVE"); entry->name = entry->path + 4; entry->size = GetTotalSpace(entry->path); entry->type = T_ROOT; diff --git a/source/godmode.c b/source/godmode.c index 3c0d936..e1c10e9 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -7,7 +7,7 @@ #include "virtual.h" #include "image.h" -#define VERSION "0.3.9" +#define VERSION "0.4.0" #define N_PANES 2 #define IMG_DRV "789I" @@ -41,8 +41,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c u32 state_curr = ((*curr_path) ? (1<<0) : 0) | ((clipboard->n_entries) ? (1<<1) : 0) | - ((GetMountState()) ? (1<<2) : 0) | - (curr_pane<<3); + (GetMountState()<<2) | + (curr_pane<<4); if (state_prev != state_curr) { ClearScreenF(true, false, COLOR_STD_BG); @@ -108,7 +108,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c ((GetWritePermissions() <= 1) ? "X - Unlock EmuNAND / image writing\nY - Unlock SysNAND writing\nR+B - Unmount SD card\n" : (GetWritePermissions() == 2) ? "X - Relock EmuNAND / image writing\nY - Unlock SysNAND writing\nR+B - Unmount SD card\n" : "X - Relock EmuNAND writing\nY - Relock SysNAND writing\nR+B - Unmount SD card\n"), - (GetMountState() && !*curr_path) ? "R+X - Unmount image\n" : "", + (*curr_path) ? "" : ((GetMountState() == IMG_RAMDRV) ? "R+X - Unmount RAM drive\n" : + (GetMountState()) ? "R+X - Unmount image\n" : "R+X - Mount RAM drive\n"), "R+L - Make a Screenshot\n", "R+\x1B\x1A - Switch to prev/next pane\n", (clipboard->n_entries) ? "SELECT - Clear Clipboard\n" : "SELECT - Restore Clipboard\n", // only if clipboard is full @@ -407,7 +408,8 @@ u32 GodMode() { } } else if (switched && (pad_state & BUTTON_B)) { // unmount SD card DeinitExtFS(); - MountImage(NULL); + if (GetMountState() != IMG_RAMDRV) + MountImage(NULL); DeinitSDCardFS(); clipboard->n_entries = 0; memset(panedata, 0x00, N_PANES * sizeof(PaneData)); @@ -463,7 +465,8 @@ u32 GodMode() { if (!(*current_path)) { // in the root folder... if (switched && !*current_path && (pad_state & BUTTON_X)) { // unmount image DeinitExtFS(); - MountImage(NULL); + if (!GetMountState()) MountRamDrive(); + else MountImage(NULL); InitExtFS(); GetDirContents(current_dir, current_path); if (clipboard->n_entries && (strcspn(clipboard->entry[0].path, IMG_DRV) == 0))