forked from Mirror/GodMode9
Various improvements to virtual file handling
This commit is contained in:
parent
4d4a037874
commit
0b735edc49
15
source/fs.c
15
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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user