From 9af01de7dc588a6073eabb2125b1b93ddbfce347 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 29 Nov 2016 16:33:56 +0100 Subject: [PATCH] Allow mounting images from any FAT based drive --- source/common.h | 2 +- source/fatfs/image.c | 24 +++++++++++++++++------- source/fatfs/image.h | 1 + source/filetype.c | 9 +++++---- source/fs.c | 21 +++++++++++++++------ source/godmode.c | 8 ++++++-- 6 files changed, 45 insertions(+), 20 deletions(-) diff --git a/source/common.h b/source/common.h index 8b122ae..a722076 100644 --- a/source/common.h +++ b/source/common.h @@ -38,7 +38,7 @@ (((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v)) // GodMode9 version -#define VERSION "0.7.8" +#define VERSION "0.7.9" // buffer area defines (in use by godmode.c) #define DIR_BUFFER (0x21000000) diff --git a/source/fatfs/image.c b/source/fatfs/image.c index 2a17a22..f14cf82 100644 --- a/source/fatfs/image.c +++ b/source/fatfs/image.c @@ -1,4 +1,5 @@ #include "image.h" +#include "sddata.h" #include "platform.h" #include "ff.h" @@ -8,6 +9,8 @@ static u32 ramdrv_size = 0; static FIL mount_file; static u32 mount_state = 0; +static char mount_path[256] = { 0 }; + int ReadImageBytes(u8* buffer, u32 offset, u32 count) { UINT bytes_read; @@ -23,7 +26,7 @@ int ReadImageBytes(u8* buffer, u32 offset, u32 count) { if (f_size(&mount_file) < offset) return -1; f_lseek(&mount_file, offset); } - ret = f_read(&mount_file, buffer, count, &bytes_read); + ret = fx_read(&mount_file, buffer, count, &bytes_read); return (ret != 0) ? (int) ret : (bytes_read != count) ? -1 : 0; } @@ -39,7 +42,7 @@ int WriteImageBytes(const u8* buffer, u32 offset, u32 count) { if (!mount_state) return FR_INVALID_OBJECT; if (f_tell(&mount_file) != offset) f_lseek(&mount_file, offset); - ret = f_write(&mount_file, buffer, count, &bytes_written); + ret = fx_write(&mount_file, buffer, count, &bytes_written); return (ret != 0) ? (int) ret : (bytes_written != count) ? -1 : 0; } @@ -65,9 +68,13 @@ u32 GetMountState(void) { return mount_state; } +const char* GetMountPath(void) { + return mount_path; +} + u32 MountRamDrive(void) { if (mount_state && (mount_state != IMG_RAMDRV)) - f_close(&mount_file); + fx_close(&mount_file); if (GetUnitPlatform() == PLATFORM_3DS) { ramdrv_buffer = RAMDRV_BUFFER_O3DS; ramdrv_size = RAMDRV_SIZE_O3DS; @@ -75,19 +82,22 @@ u32 MountRamDrive(void) { 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 = IdentifyFileType(path); + u32 type = (path) ? IdentifyFileType(path) : 0; if (mount_state) { - if (mount_state != IMG_RAMDRV) f_close(&mount_file); + if (mount_state != IMG_RAMDRV) fx_close(&mount_file); mount_state = 0; + *mount_path = 0; } - if (!path || !type) return 0; - if (f_open(&mount_file, path, FA_READ | FA_WRITE | FA_OPEN_EXISTING) != FR_OK) + if (!type) return 0; + if (fx_open(&mount_file, path, FA_READ | FA_WRITE | FA_OPEN_EXISTING) != FR_OK) return 0; f_lseek(&mount_file, 0); f_sync(&mount_file); + strncpy(mount_path, path, 255); return (mount_state = type); } diff --git a/source/fatfs/image.h b/source/fatfs/image.h index 0154edb..7aad0f8 100644 --- a/source/fatfs/image.h +++ b/source/fatfs/image.h @@ -13,5 +13,6 @@ int SyncImage(void); u64 GetMountSize(void); u32 GetMountState(void); +const char* GetMountPath(void); u32 MountRamDrive(void); u32 MountImage(const char* path); diff --git a/source/filetype.c b/source/filetype.c index 2c4ee40..5f728e3 100644 --- a/source/filetype.c +++ b/source/filetype.c @@ -1,21 +1,22 @@ #include "filetype.h" +#include "sddata.h" #include "game.h" #include "ff.h" u32 IdentifyFileType(const char* path) { u8 __attribute__((aligned(16))) header[0x200]; // minimum required size FIL file; - if (f_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) + if (fx_open(&file, path, FA_READ | FA_OPEN_EXISTING) != FR_OK) return 0; f_lseek(&file, 0); f_sync(&file); UINT fsize = f_size(&file); UINT bytes_read; - if ((f_read(&file, header, 0x200, &bytes_read) != FR_OK) || (bytes_read != 0x200)) { - f_close(&file); + if ((fx_read(&file, header, 0x200, &bytes_read) != FR_OK) || (bytes_read != 0x200)) { + fx_close(&file); return 0; } - f_close(&file); + fx_close(&file); if ((getbe32(header + 0x100) == 0x4E435344) && (getbe64(header + 0x110) == (u64) 0x0104030301000000) && (getbe64(header + 0x108) == (u64) 0) && (fsize >= 0x8FC8000)) { diff --git a/source/fs.c b/source/fs.c index 0a306a8..a1a0549 100644 --- a/source/fs.c +++ b/source/fs.c @@ -221,6 +221,11 @@ bool CheckWritePermissions(const char* path) { int drvtype = DriveType(path); u32 perm; + // check mounted image write permissions + if ((drvtype & DRV_IMAGE) && !CheckWritePermissions(GetMountPath())) + return false; // endless loop when mounted file inside image, but not possible + + // check drive type, get permission type if (drvtype & DRV_SYSNAND) { perm = PERM_SYSNAND; snprintf(area_name, 16, "the SysNAND"); @@ -233,15 +238,15 @@ bool CheckWritePermissions(const char* path) { } else if (drvtype & DRV_EMUNAND) { perm = PERM_EMUNAND; snprintf(area_name, 16, "the EmuNAND"); + } else if (drvtype & DRV_GAME) { + perm = PERM_GAME; + snprintf(area_name, 16, "game images"); } else if (drvtype & DRV_IMAGE) { perm = PERM_IMAGE; snprintf(area_name, 16, "images"); } else if (drvtype & DRV_MEMORY) { perm = PERM_MEMORY; snprintf(area_name, 16, "memory areas"); - } else if (drvtype & DRV_GAME) { - perm = PERM_GAME; - snprintf(area_name, 16, "game images"); } else if ((drvtype & DRV_ALIAS) || (strncmp(path, "0:/Nintendo 3DS", 15) == 0)) { perm = PERM_SDDATA; snprintf(area_name, 16, "SD system data"); @@ -292,9 +297,9 @@ bool SetWritePermissions(u32 perm, bool add_perm) { if (!ShowUnlockSequence(2, "You want to enable image\nwriting permissions.")) return false; break; - case PERM_SDDATA: - if (!ShowUnlockSequence(2, "You want to enable SD data\nwriting permissions.")) - return false; + case PERM_GAME: + ShowPrompt(false, "Unlock write permission for\ngame images is not allowed."); + return false; break; #ifndef SAFEMODE case PERM_SYSNAND: @@ -309,6 +314,10 @@ bool SetWritePermissions(u32 perm, bool add_perm) { if (!ShowUnlockSequence(4, "!Better be careful!\n \nYou want to enable memory\nwriting permissions.\nWriting to certain areas may\nlead to unexpected results.")) return false; break; + case PERM_SDDATA: + if (!ShowUnlockSequence(2, "You want to enable SD data\nwriting permissions.")) + return false; + break; case PERM_ALL: if (!ShowUnlockSequence(3, "!Better be careful!\n \nYou want to enable ALL\nwriting permissions.\nThis enables you to do some\nreally dangerous stuff!")) return false; diff --git a/source/godmode.c b/source/godmode.c index b78c459..e75df60 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -628,8 +628,11 @@ u32 GodMode() { int injectable = ((clipboard->n_entries == 1) && (clipboard->entry[0].type == T_FILE) && (file_drvtype & DRV_FAT) && - (strncmp(clipboard->entry[0].path, curr_entry->path, 256) != 0)) ? (int) ++n_opt : -1; - int mountable = (file_type && (file_drvtype & DRV_SDCARD)) ? (int) ++n_opt : -1; + (strncmp(clipboard->entry[0].path, curr_entry->path, 256) != 0)) ? + (int) ++n_opt : -1; + int mountable = (file_type && (file_drvtype & DRV_FAT) && + !(file_drvtype & (DRV_IMAGE|DRV_RAMDRIVE))) ? + (int) ++n_opt : -1; int searchdrv = (curr_drvtype & DRV_SEARCH) ? (int) ++n_opt : -1; TruncateString(pathstr, curr_entry->path, 32, 8); @@ -692,6 +695,7 @@ u32 GodMode() { if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE)) clipboard->n_entries = 0; // remove last mounted image clipboard entries DeinitExtFS(); + InitExtFS(); u32 mount_state = MountImage(curr_entry->path); InitExtFS(); InitVGameDrive();