Allow mounting images from any FAT based drive

This commit is contained in:
d0k3 2016-11-29 16:33:56 +01:00
parent 4df338b8a0
commit 9af01de7dc
6 changed files with 45 additions and 20 deletions

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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)) {

View File

@ -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,8 +297,8 @@ 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."))
case PERM_GAME:
ShowPrompt(false, "Unlock write permission for\ngame images is not allowed.");
return false;
break;
#ifndef SAFEMODE
@ -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;

View File

@ -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();