mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Added ability to copy virtual files
This commit is contained in:
parent
50c9091d2c
commit
4d4a037874
140
source/fs.c
140
source/fs.c
@ -147,6 +147,131 @@ bool FileGetData(const char* path, u8* data, size_t size, size_t foffset)
|
||||
return (bytes_read == size);
|
||||
}
|
||||
|
||||
bool PathCopyVirtual(const char* destdir, const char* orig) {
|
||||
char dest[256]; // maximum path name length in FAT
|
||||
char* oname = strrchr(orig, '/');
|
||||
char deststr[36 + 1];
|
||||
char origstr[36 + 1];
|
||||
bool ret = true;
|
||||
|
||||
if (oname == NULL) return false; // not a proper origin path
|
||||
oname++;
|
||||
snprintf(dest, 256, "%s/%s", destdir, oname);
|
||||
|
||||
TruncateString(deststr, dest, 36, 8);
|
||||
TruncateString(origstr, orig, 36, 8);
|
||||
|
||||
if (IsVirtualPath(dest) && IsVirtualPath(orig)) { // virtual to virtual
|
||||
VirtualFile dvfile;
|
||||
VirtualFile ovfile;
|
||||
u32 osize;
|
||||
|
||||
if (!FindVirtualFile(&dvfile, dest))
|
||||
return false;
|
||||
if (!FindVirtualFile(&ovfile, orig))
|
||||
return false;
|
||||
osize = ovfile.size;
|
||||
if (dvfile.size != osize) { // almost impossible, but so what...
|
||||
ShowPrompt(false, "Virtual file size mismatch:\n%s\n%s", origstr, deststr);
|
||||
return false;
|
||||
}
|
||||
if ((dvfile.keyslot == ovfile.keyslot) && (dvfile.offset == ovfile.offset)) // this improves copy times
|
||||
dvfile.keyslot = ovfile.keyslot = 0xFF;
|
||||
|
||||
DeinitNandFS();
|
||||
if (!ShowProgress(0, 0, orig)) ret = false;
|
||||
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
|
||||
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
|
||||
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0)
|
||||
ret = false;
|
||||
if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
|
||||
ret = false;
|
||||
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, read_bytes) != 0)
|
||||
ret = false;
|
||||
}
|
||||
ShowProgress(1, 1, orig);
|
||||
InitNandFS();
|
||||
} else if (IsVirtualPath(dest)) { // SD card to virtual (other FAT not allowed!)
|
||||
VirtualFile dvfile;
|
||||
FIL ofile;
|
||||
u32 osize;
|
||||
|
||||
if (!FindVirtualFile(&dvfile, dest))
|
||||
return false;
|
||||
if (f_open(&ofile, orig, FA_READ | FA_OPEN_EXISTING) != FR_OK)
|
||||
return false;
|
||||
f_lseek(&ofile, 0);
|
||||
f_sync(&ofile);
|
||||
osize = f_size(&ofile);
|
||||
if (dvfile.size != osize) {
|
||||
char osizestr[32];
|
||||
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;
|
||||
}
|
||||
|
||||
DeinitNandFS();
|
||||
if (!ShowProgress(0, 0, orig)) ret = false;
|
||||
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
|
||||
UINT bytes_read = 0;
|
||||
if (f_read(&ofile, MAIN_BUFFER, MAIN_BUFFER_SIZE, &bytes_read) != FR_OK)
|
||||
ret = false;
|
||||
if (!ShowProgress(pos + (bytes_read / 2), osize, orig))
|
||||
ret = false;
|
||||
if (WriteVirtualFile(&dvfile, MAIN_BUFFER, pos, bytes_read) != 0)
|
||||
ret = false;
|
||||
}
|
||||
ShowProgress(1, 1, orig);
|
||||
f_close(&ofile);
|
||||
InitNandFS();
|
||||
} else if (IsVirtualPath(orig)) { // virtual to SD card (other FAT not allowed)
|
||||
VirtualFile ovfile;
|
||||
FIL dfile;
|
||||
u32 osize;
|
||||
|
||||
if (!FindVirtualFile(&ovfile, orig))
|
||||
return false;
|
||||
// check if destination exists
|
||||
if (f_stat(dest, NULL) == FR_OK) {
|
||||
if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?", deststr))
|
||||
return false;
|
||||
}
|
||||
if (f_open(&dfile, dest, FA_WRITE | FA_CREATE_ALWAYS) != FR_OK)
|
||||
return false;
|
||||
f_lseek(&dfile, 0);
|
||||
f_sync(&dfile);
|
||||
osize = ovfile.size;
|
||||
if (GetFreeSpace(dest) < osize) {
|
||||
ShowPrompt(false, "Error: File is too big for destination");
|
||||
f_close(&dfile);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!ShowProgress(0, 0, orig)) ret = false;
|
||||
for (size_t pos = 0; (pos < osize) && ret; pos += MAIN_BUFFER_SIZE) {
|
||||
UINT read_bytes = min(MAIN_BUFFER_SIZE, osize - pos);
|
||||
UINT bytes_written = 0;
|
||||
if (ReadVirtualFile(&ovfile, MAIN_BUFFER, pos, read_bytes) != 0)
|
||||
ret = false;
|
||||
if (!ShowProgress(pos + (read_bytes / 2), osize, orig))
|
||||
ret = false;
|
||||
if (f_write(&dfile, MAIN_BUFFER, read_bytes, &bytes_written) != FR_OK)
|
||||
ret = false;
|
||||
if (read_bytes != bytes_written)
|
||||
ret = false;
|
||||
}
|
||||
ShowProgress(1, 1, orig);
|
||||
f_close(&dfile);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
|
||||
FILINFO fno = {.lfname = NULL};
|
||||
bool ret = false;
|
||||
@ -261,13 +386,22 @@ bool PathCopyWorker(char* dest, char* orig, bool overwrite) {
|
||||
}
|
||||
|
||||
bool PathCopy(const char* destdir, const char* orig) {
|
||||
if (!CheckWritePermissions(destdir)) return false;
|
||||
if (IsVirtualPath(destdir) || IsVirtualPath(orig)) {
|
||||
// users are inventive...
|
||||
if ((PathToNumFS(orig) > 0) && IsVirtualPath(destdir)) {
|
||||
ShowPrompt(false, "Only files from SD card are accepted");
|
||||
return false;
|
||||
}
|
||||
return PathCopyVirtual(destdir, orig);
|
||||
} else {
|
||||
char fdpath[256]; // 256 is the maximum length of a full path
|
||||
char fopath[256];
|
||||
if (!CheckWritePermissions(destdir)) return false;
|
||||
strncpy(fdpath, destdir, 255);
|
||||
strncpy(fopath, orig, 255);
|
||||
return PathCopyWorker(fdpath, fopath, false);
|
||||
}
|
||||
}
|
||||
|
||||
bool PathDeleteWorker(char* fpath) {
|
||||
FILINFO fno = {.lfname = NULL};
|
||||
@ -401,8 +535,8 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
||||
for (u32 pdrv = 0; (pdrv < MAX_FS+2) && (n_entries < MAX_ENTRIES); pdrv++) {
|
||||
DirEntry* entry = &(contents->entry[n_entries]);
|
||||
if ((pdrv < MAX_FS) && !fs_mounted[pdrv]) continue;
|
||||
if ((pdrv == MAX_FS+0) && (!fs_mounted[1] || !fs_mounted[2] || !fs_mounted[3])) continue;
|
||||
if ((pdrv == MAX_FS+1) && (!fs_mounted[4] || !fs_mounted[5] || !fs_mounted[6])) continue;
|
||||
if ((pdrv == MAX_FS+0) && (!fs_mounted[1])) continue;
|
||||
if ((pdrv == MAX_FS+1) && (!fs_mounted[4])) continue;
|
||||
memset(entry->path, 0x00, 64);
|
||||
snprintf(entry->path + 0, 4, "%s:", drvnum[pdrv]);
|
||||
snprintf(entry->path + 4, 32, "[%s:] %s", drvnum[pdrv], drvname[pdrv]);
|
||||
|
@ -5,24 +5,24 @@
|
||||
#define VFLAG_ON_N3DS NAND_TYPE_N3DS
|
||||
#define VFLAG_ON_NO3DS NAND_TYPE_NO3DS
|
||||
#define VFLAG_ON_ALL (VFLAG_ON_O3DS | VFLAG_ON_N3DS | VFLAG_ON_NO3DS)
|
||||
#define VFLAG_NAND_SIZE (1<<29)
|
||||
#define VFLAG_ON_EMUNAND (1<<30)
|
||||
#define VFLAG_NAND_SIZE (1<<30)
|
||||
#define VFLAG_ON_EMUNAND (1<<31)
|
||||
|
||||
VirtualFile virtualFileTemplates[] = {
|
||||
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL },
|
||||
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL },
|
||||
{ "agbsave.bin" , 0x0B100000, 0x00030000, 0x07, VFLAG_ON_ALL },
|
||||
{ "firm0.bin" , 0x0B130000, 0x00400000, 0x06, VFLAG_ON_ALL },
|
||||
{ "firm1.bin" , 0x0B530000, 0x00400000, 0x06, VFLAG_ON_ALL },
|
||||
{ "ctrnand_fat.bin" , 0x0B95CA00, 0x2F3E3600, 0x04, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x05, VFLAG_ON_N3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x04, VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x2F5D0000, 0x04, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_ALL | VFLAG_NAND_SIZE | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS | VFLAG_EXT_NAND_REMOUNT },
|
||||
{ "ctrnand_fat.bin" , 0x0B95CA00, 0x2F3E3600, 0x04, VFLAG_ON_O3DS },
|
||||
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x05, VFLAG_ON_N3DS },
|
||||
{ "ctrnand_fat.bin" , 0x0B95AE00, 0x41D2D200, 0x04, VFLAG_ON_NO3DS },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x2F5D0000, 0x04, VFLAG_ON_O3DS },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x05, VFLAG_ON_N3DS },
|
||||
{ "ctrnand_full.bin" , 0x0B930000, 0x41ED0000, 0x04, VFLAG_ON_NO3DS },
|
||||
{ "nand.bin" , 0x00000000, 0x00000000, 0xFF, VFLAG_ON_ALL | VFLAG_NAND_SIZE },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS },
|
||||
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS },
|
||||
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_ALL },
|
||||
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_ALL }
|
||||
};
|
||||
|
@ -3,8 +3,6 @@
|
||||
#include "common.h"
|
||||
#include "nand.h"
|
||||
|
||||
#define VFLAG_EXT_NAND_REMOUNT (1<<31)
|
||||
|
||||
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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user