From 0b735edc498032c75f78549d724ab81705e7edfe Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 22 Mar 2016 14:30:11 +0100 Subject: [PATCH] Various improvements to virtual file handling --- source/fs.c | 15 +++++++++++---- source/nand/nand.c | 16 +++++++++++----- source/nand/nand.h | 4 +--- source/nand/virtual.c | 27 +++++++++++++++++++-------- source/nand/virtual.h | 6 +++++- 5 files changed, 47 insertions(+), 21 deletions(-) diff --git a/source/fs.c b/source/fs.c index f3bed21..e081eb6 100644 --- a/source/fs.c +++ b/source/fs.c @@ -70,7 +70,7 @@ bool CheckWritePermissions(const char* path) { int pdrv = PathToNumFS(path); if (pdrv < 0) { if (IsVirtualPath(path)) // this is a hack, but okay for now - pdrv = (*path == 'S') ? 1 : 4; + pdrv = (IsVirtualPath(path) == VRT_SYSNAND) ? 1 : 4; else return false; } @@ -208,9 +208,16 @@ bool PathCopyVirtual(const char* destdir, const char* orig) { char dsizestr[32]; FormatBytes(osizestr, osize); FormatBytes(dsizestr, dvfile.size); - ShowPrompt(false, "File size mismatch:\n%s (%s)\n%s (%s)", origstr, osizestr, deststr, dsizestr); - f_close(&ofile); - return false; + if (dvfile.size > osize) { + if (!ShowPrompt(true, "File smaller than available space:\n%s (%s)\n%s (%s)\nContinue?", origstr, osizestr, deststr, dsizestr)) { + f_close(&ofile); + return false; + } + } else { + ShowPrompt(false, "File bigger than available space:\n%s (%s)\n%s (%s)", origstr, osizestr, deststr, dsizestr); + f_close(&ofile); + return false; + } } DeinitNandFS(); diff --git a/source/nand/nand.c b/source/nand/nand.c index 7e88a1c..f080b99 100644 --- a/source/nand/nand.c +++ b/source/nand/nand.c @@ -163,12 +163,18 @@ u8 CheckNandType(bool check_emunand) return NAND_TYPE_UNK; } +u64 GetNandSizeSectors(bool size_emunand) +{ + if (size_emunand) { // for EmuNAND + u32 emunand_max_sectors = GetPartitionOffsetSector("0:") - (emunand_base_sector + 1); // +1 for safety + u32 emunand_min_sectors = (emunand_base_sector % 0x200000 == 0) ? getMMCDevice(0)->total_size : + (GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800; + return (emunand_min_sectors > emunand_max_sectors) ? 0 : emunand_min_sectors; + } else return getMMCDevice(0)->total_size; // for SysNAND +} + bool InitEmuNandBase(void) { - emunand_base_sector = 0x000000; - if (GetPartitionOffsetSector("0:") <= getMMCDevice(0)->total_size) - return false; - emunand_base_sector = 0x000000; // GW type EmuNAND if (CheckNandType(true) != NAND_TYPE_UNK) return true; @@ -177,6 +183,6 @@ bool InitEmuNandBase(void) if (CheckNandType(true) != NAND_TYPE_UNK) return true; - emunand_base_sector = 0x000000; + if (GetPartitionOffsetSector("0:") > getMMCDevice(0)->total_size) return false; } diff --git a/source/nand/nand.h b/source/nand/nand.h index a9060c5..b599d2d 100644 --- a/source/nand/nand.h +++ b/source/nand/nand.h @@ -13,9 +13,7 @@ void CryptNand(u8* buffer, u32 sector, u32 count, u32 keyslot); int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, bool read_emunand); int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, bool write_emunand); +u64 GetNandSizeSectors(bool size_emunand); u8 CheckNandType(bool check_emunand); bool InitEmuNandBase(void); -u32 GetEmuNandBase(void); -u32 SwitchEmuNandBase(int start_sector); - diff --git a/source/nand/virtual.c b/source/nand/virtual.c index 0644329..68a0a0d 100644 --- a/source/nand/virtual.c +++ b/source/nand/virtual.c @@ -1,5 +1,4 @@ #include "virtual.h" -#include "sdmmc.h" #define VFLAG_ON_O3DS NAND_TYPE_O3DS #define VFLAG_ON_N3DS NAND_TYPE_N3DS @@ -27,24 +26,33 @@ VirtualFile virtualFileTemplates[] = { { "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_ALL } }; -bool IsVirtualPath(const char* path) { - return (strncmp(path, "S:", 2) == 0) || (strncmp(path, "E:", 2) == 0); +u32 IsVirtualPath(const char* path) { + u32 plen = strnlen(path, 16); + if (strncmp(path, "S:/", (plen >= 3) ? 3 : 2) == 0) + return VRT_SYSNAND; + else if (strncmp(path, "E:/", (plen >= 3) ? 3 : 2) == 0) + return VRT_EMUNAND; + return 0; } bool FindVirtualFile(VirtualFile* vfile, const char* path) { char* fname = strchr(path, '/'); - bool on_emunand = (*path == 'E'); - u8 nand_type = CheckNandType(on_emunand); + bool on_emunand = false; + u8 nand_type = 0; // fix the name if (!fname) return false; fname++; - // more safety checks + // check path vailidity if (!IsVirtualPath(path) || (fname - path != 3)) return false; + // check NAND type + on_emunand = (IsVirtualPath(path) == VRT_EMUNAND); + nand_type = CheckNandType(on_emunand); + // parse the template list, get the correct one u32 n_templates = sizeof(virtualFileTemplates) / sizeof(VirtualFile); VirtualFile* curr_template = NULL; @@ -60,8 +68,11 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path) memcpy(vfile, curr_template, sizeof(VirtualFile)); // process special flags - if (vfile->flags & VFLAG_NAND_SIZE) - vfile->size = getMMCDevice(0)->total_size * 0x200; + if (vfile->flags & VFLAG_NAND_SIZE) { + if (on_emunand && (GetNandSizeSectors(false) != GetNandSizeSectors(true))) + return false; // EmuNAND is too small + vfile->size = GetNandSizeSectors(false) * 0x200; + } if (on_emunand) vfile->flags |= VFLAG_ON_EMUNAND; return true; diff --git a/source/nand/virtual.h b/source/nand/virtual.h index 846d7b9..b84a533 100644 --- a/source/nand/virtual.h +++ b/source/nand/virtual.h @@ -3,6 +3,10 @@ #include "common.h" #include "nand.h" +#define VRT_NONE 0 +#define VRT_SYSNAND 1 +#define VRT_EMUNAND 2 + static const char* virtualFileList[] = { // must have a match in virtualFileTemplates[] "twln.bin", "twlp.bin", "agbsave.bin", "firm0.bin", "firm1.bin", "ctrnand_fat.bin", "ctrnand_full.bin", "nand.bin", "nand_minsize.bin", "nand_hdr.bin", "sector0x96.bin" @@ -17,7 +21,7 @@ typedef struct { u32 flags; } __attribute__((packed)) VirtualFile; -bool IsVirtualPath(const char* path); +u32 IsVirtualPath(const char* path); bool FindVirtualFile(VirtualFile* vfile, const char* path); int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count); int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count);