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))
// GodMode9 version
#define VERSION "0.8.6"
#define VERSION "0.8.7"
// input / output paths
#define INPUT_PATHS "0:", "0:/files9", "0:/Decrypt9"

View File

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

View File

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

View File

@ -3,8 +3,6 @@
#include "common.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 WriteImageBytes(const u8* buffer, u64 offset, u64 count);
int ReadImageSectors(u8* buffer, u32 sector, u32 count);
@ -14,5 +12,4 @@ int SyncImage(void);
u64 GetMountSize(void);
u32 GetMountState(void);
const char* GetMountPath(void);
u32 MountRamDrive(void);
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)) {
if (pdrv == 0) {
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;
} else if ((pdrv >= 1) && (pdrv <= 3)) {
type = DRV_FAT | DRV_SYSNAND | DRV_STDFAT;
@ -69,9 +69,10 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
if (!DriveType(drvnum[pdrv])) continue; // drive not available
memset(entry->path, 0x00, 64);
snprintf(entry->path + 0, 4, drvnum[pdrv]);
if ((pdrv == 7) && ((GetMountState() == IMG_FAT) || (GetMountState() == IMG_RAMDRV)))
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], // FAT image / RAM drive special handling
(GetMountState() == IMG_FAT) ? "FAT IMAGE" : "RAMDRIVE");
if ((pdrv == 7) && (GetMountState() == IMG_FAT)) // FAT image handling
snprintf(entry->path + 4, 32, "[%s] %s", drvnum[pdrv], "FAT IMAGE");
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
snprintf(entry->path + 4, 32, "[%s] %s %s", drvnum[pdrv],
(GetMountState() == GAME_CIA ) ? "CIA" :

View File

@ -25,6 +25,11 @@ bool InitExtFS() {
snprintf(fsname, 7, "%lu:", i);
if (fs_mounted[i]) continue;
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("B:", "0:", "4:/private/movable.sed", 1);
@ -53,23 +58,6 @@ bool InitImgFS(const char* path) {
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() {
SetupNandSdDrive(NULL, NULL, NULL, 0);
SetupNandSdDrive(NULL, NULL, NULL, 1);
@ -80,7 +68,7 @@ void DeinitExtFS() {
f_mount(NULL, fsname, 1);
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);
InitVGameDrive();
}
@ -88,10 +76,8 @@ void DeinitExtFS() {
}
void DeinitSDCardFS() {
if (GetMountState() != IMG_RAMDRV) {
MountImage(NULL);
InitVGameDrive();
}
MountImage(NULL);
InitVGameDrive();
if (fs_mounted[0]) {
f_mount(NULL, "0:", 1);
fs_mounted[0] = false;

View File

@ -12,9 +12,6 @@ bool InitExtFS();
// mount and init image file system
bool InitImgFS(const char* path);
// init RAM drive filesystem (unmounts image)
bool InitRamDriveFS();
// deinitialize external filesystem
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") :
((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"),
(*curr_path) ? "" : ((GetMountState() == IMG_RAMDRV) ? "R+X - Unmount RAM drive\n" :
(GetMountState()) ? "R+X - Unmount image\n" : "R+X - Mount RAM drive\n"),
(*curr_path) ? "" : "R+X - Reinit filesystem\n",
(*curr_path) ? "R+A - Search directory\n" : "R+A - Search drive\n",
"R+L - Make a Screenshot\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
user_select = (n_opt > 1) ? (int) ShowSelectPrompt(n_opt, optionstr, pathstr) : n_opt;
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
InitImgFS(curr_entry->path);
if (!(DriveType("7:")||DriveType("8:")||DriveType("9:")||DriveType("G:"))) {
if (!(DriveType("7:")||DriveType("G:"))) {
ShowPrompt(false, "Mounting image: failed");
InitImgFS(NULL);
} else {
@ -663,7 +662,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur
*current_path = '\0';
GetDirContents(current_dir, current_path);
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;
strncpy(current_path, current_dir->entry[i].path, 256);
GetDirContents(current_dir, current_path);
@ -937,11 +936,14 @@ u32 GodMode() {
// highly specific commands
if (!*current_path) { // in the root folder...
if (switched && (pad_state & BUTTON_X)) { // unmount image
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & (DRV_IMAGE|DRV_RAMDRIVE)))
if (switched && (pad_state & BUTTON_X)) { // reinit file system / unmount image
if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE))
clipboard->n_entries = 0; // remove last mounted image clipboard entries
if (!GetMountState()) InitRamDriveFS();
else InitImgFS(NULL);
DeinitExtFS();
DeinitSDCardFS();
InitSDCardFS();
InitExtFS();
ClearScreenF(false, true, COLOR_STD_BG);
GetDirContents(current_dir, current_path);
} else if (switched && (pad_state & BUTTON_Y)) {
SetWritePermissions((GetWritePermissions() > PERM_BASE) ? PERM_BASE : PERM_ALL, false);