mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Added virtual memory drive
This commit is contained in:
parent
cdc3cf6f27
commit
f0c7079e08
11
source/fs.c
11
source/fs.c
@ -8,7 +8,7 @@
|
|||||||
#define MAIN_BUFFER_SIZE (0x100000) // must be multiple of 0x200
|
#define MAIN_BUFFER_SIZE (0x100000) // must be multiple of 0x200
|
||||||
|
|
||||||
#define NORM_FS 10
|
#define NORM_FS 10
|
||||||
#define VIRT_FS 3
|
#define VIRT_FS 4
|
||||||
|
|
||||||
// don't use this area for anything else!
|
// don't use this area for anything else!
|
||||||
static FATFS* fs = (FATFS*)0x20316000;
|
static FATFS* fs = (FATFS*)0x20316000;
|
||||||
@ -78,7 +78,8 @@ bool CheckWritePermissions(const char* path) {
|
|||||||
int pdrv = PathToNumFS(path);
|
int pdrv = PathToNumFS(path);
|
||||||
if (pdrv < 0) {
|
if (pdrv < 0) {
|
||||||
if (IsVirtualPath(path)) // this is a hack, but okay for now
|
if (IsVirtualPath(path)) // this is a hack, but okay for now
|
||||||
pdrv = (IsVirtualPath(path) == VRT_SYSNAND) ? 1 : 4;
|
pdrv = (IsVirtualPath(path) == VRT_MEMORY) ? 10 :
|
||||||
|
(IsVirtualPath(path) == VRT_SYSNAND) ? 1 : 4;
|
||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +99,9 @@ bool CheckWritePermissions(const char* path) {
|
|||||||
if (ShowPrompt(true, "Writing to the SD card is locked!\nUnlock it now?"))
|
if (ShowPrompt(true, "Writing to the SD card is locked!\nUnlock it now?"))
|
||||||
return SetWritePermissions(1);
|
return SetWritePermissions(1);
|
||||||
return false;
|
return false;
|
||||||
|
} else if (pdrv >= 10) {
|
||||||
|
ShowPrompt(false, "Writing to memory is forbidden!");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -594,9 +598,10 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
|||||||
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP",
|
"EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP",
|
||||||
"IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP",
|
"IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP",
|
||||||
"SYSNAND VIRTUAL", "EMUNAND VIRTUAL", "IMGNAND VIRTUAL",
|
"SYSNAND VIRTUAL", "EMUNAND VIRTUAL", "IMGNAND VIRTUAL",
|
||||||
|
"MEMORY VIRTUAL"
|
||||||
};
|
};
|
||||||
static const char* drvnum[] = {
|
static const char* drvnum[] = {
|
||||||
"0:", "1:", "2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "S:", "E:", "I:"
|
"0:", "1:", "2:", "3:", "4:", "5:", "6:", "7:", "8:", "9:", "S:", "E:", "I:", "M:"
|
||||||
};
|
};
|
||||||
u32 n_entries = 0;
|
u32 n_entries = 0;
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
#define VERSION "0.3.1"
|
#define VERSION "0.3.3"
|
||||||
|
|
||||||
#define N_PANES 2
|
#define N_PANES 2
|
||||||
#define IMG_DRV "789I"
|
#define IMG_DRV "789I"
|
||||||
|
@ -251,7 +251,7 @@ int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 n
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 CheckNandType(u32 nand_src)
|
u32 CheckNandType(u32 nand_src)
|
||||||
{
|
{
|
||||||
if (ReadNandSectors(NAND_BUFFER, 0, 1, 0xFF, nand_src) != 0)
|
if (ReadNandSectors(NAND_BUFFER, 0, 1, 0xFF, nand_src) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -18,6 +18,6 @@ int ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src);
|
|||||||
int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest);
|
int WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest);
|
||||||
|
|
||||||
u64 GetNandSizeSectors(u32 src);
|
u64 GetNandSizeSectors(u32 src);
|
||||||
u8 CheckNandType(u32 src);
|
u32 CheckNandType(u32 src);
|
||||||
|
|
||||||
bool InitEmuNandBase(void);
|
bool InitEmuNandBase(void);
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#define VRT_ANYNAND (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND)
|
||||||
#define VFLAG_ON_O3DS NAND_TYPE_O3DS
|
#define VFLAG_ON_O3DS NAND_TYPE_O3DS
|
||||||
#define VFLAG_ON_N3DS NAND_TYPE_N3DS
|
#define VFLAG_ON_N3DS NAND_TYPE_N3DS
|
||||||
#define VFLAG_ON_NO3DS NAND_TYPE_NO3DS
|
#define VFLAG_ON_NO3DS NAND_TYPE_NO3DS
|
||||||
#define VFLAG_ON_ALL (VFLAG_ON_O3DS | VFLAG_ON_N3DS | VFLAG_ON_NO3DS)
|
#define VFLAG_ON_ALL (VFLAG_ON_O3DS | VFLAG_ON_N3DS | VFLAG_ON_NO3DS)
|
||||||
|
#define VFLAG_ON_MEMORY VRT_MEMORY
|
||||||
#define VFLAG_NAND_SIZE (1<<31)
|
#define VFLAG_NAND_SIZE (1<<31)
|
||||||
|
|
||||||
|
// see: http://3dbrew.org/wiki/Flash_Filesystem#NAND_structure
|
||||||
|
// see: http://3dbrew.org/wiki/Memory_layout#ARM9
|
||||||
VirtualFile virtualFileTemplates[] = {
|
VirtualFile virtualFileTemplates[] = {
|
||||||
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL },
|
{ "twln.bin" , 0x00012E00, 0x08FB5200, 0x03, VFLAG_ON_ALL },
|
||||||
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL },
|
{ "twlp.bin" , 0x09011A00, 0x020B6600, 0x03, VFLAG_ON_ALL },
|
||||||
@ -22,7 +27,15 @@ VirtualFile virtualFileTemplates[] = {
|
|||||||
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS },
|
{ "nand_minsize.bin" , 0x00000000, 0x3AF00000, 0xFF, VFLAG_ON_O3DS },
|
||||||
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS },
|
{ "nand_minsize.bin" , 0x00000000, 0x4D800000, 0xFF, VFLAG_ON_N3DS | VFLAG_ON_NO3DS },
|
||||||
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_ALL },
|
{ "sector0x96.bin" , 0x00012C00, 0x00000200, 0xFF, VFLAG_ON_ALL },
|
||||||
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_ALL }
|
{ "nand_hdr.bin" , 0x00000000, 0x00000200, 0xFF, VFLAG_ON_ALL },
|
||||||
|
{ "itcm.dmp" , 0x01FF8000, 0x00008000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "arm9internal.dmp" , 0x08000000, 0x00100000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "vram.dmp" , 0x18000000, 0x00600000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "dsp.dmp" , 0x1FF00000, 0x00080000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "axiwram.dmp" , 0x1FF80000, 0x00080000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "fcram.dmp" , 0x20000000, 0x08000000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "dtcm.dmp" , 0xFFFF0000, 0x00004000, 0xFF, VFLAG_ON_MEMORY },
|
||||||
|
{ "bootrom_unp.dmp" , 0xFFFF0000, 0x00008000, 0xFF, VFLAG_ON_MEMORY }
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 IsVirtualPath(const char* path) {
|
u32 IsVirtualPath(const char* path) {
|
||||||
@ -33,44 +46,45 @@ u32 IsVirtualPath(const char* path) {
|
|||||||
return VRT_EMUNAND;
|
return VRT_EMUNAND;
|
||||||
else if (strncmp(path, "I:/", (plen >= 3) ? 3 : 2) == 0)
|
else if (strncmp(path, "I:/", (plen >= 3) ? 3 : 2) == 0)
|
||||||
return VRT_IMGNAND;
|
return VRT_IMGNAND;
|
||||||
|
else if (strncmp(path, "M:/", (plen >= 3) ? 3 : 2) == 0)
|
||||||
|
return VRT_MEMORY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckVirtualPath(const char* path) {
|
bool CheckVirtualPath(const char* path) {
|
||||||
u32 vp_nand = IsVirtualPath(path);
|
u32 virtual_src = IsVirtualPath(path);
|
||||||
if ((vp_nand == VRT_EMUNAND) || (vp_nand == VRT_IMGNAND)) {
|
if ((virtual_src == VRT_EMUNAND) || (virtual_src == VRT_IMGNAND)) {
|
||||||
return GetNandSizeSectors(vp_nand);
|
return GetNandSizeSectors(virtual_src);
|
||||||
}
|
}
|
||||||
return vp_nand; // this is safe for SysNAND because we re-check for slot0x05 crypto
|
return virtual_src; // this is safe for SysNAND & memory
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size)
|
bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size)
|
||||||
{
|
{
|
||||||
char* fname = strchr(path, '/');
|
char* fname = strchr(path, '/');
|
||||||
u8 nand_src = 0;
|
u32 virtual_src = 0;
|
||||||
u8 nand_type = 0;
|
u32 virtual_type = 0;
|
||||||
|
|
||||||
// fix the name
|
// fix the name
|
||||||
if (!fname) return false;
|
if (!fname) return false;
|
||||||
fname++;
|
fname++;
|
||||||
|
|
||||||
// check path vailidity
|
// check path vailidity
|
||||||
nand_src = IsVirtualPath(path);
|
virtual_src = IsVirtualPath(path);
|
||||||
if (!nand_src || (fname - path != 3))
|
if (!virtual_src || (fname - path != 3))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check NAND type
|
// check NAND type
|
||||||
nand_type = CheckNandType(nand_src);
|
virtual_type = (virtual_src & VRT_ANYNAND) ? CheckNandType(virtual_src) : virtual_src;
|
||||||
|
|
||||||
// parse the template list, get the correct one
|
// parse the template list, get the correct one
|
||||||
u32 n_templates = sizeof(virtualFileTemplates) / sizeof(VirtualFile);
|
u32 n_templates = sizeof(virtualFileTemplates) / sizeof(VirtualFile);
|
||||||
VirtualFile* curr_template = NULL;
|
VirtualFile* curr_template = NULL;
|
||||||
for (u32 i = 0; i < n_templates; i++) {
|
for (u32 i = 0; i < n_templates; i++) {
|
||||||
curr_template = &virtualFileTemplates[i];
|
curr_template = &virtualFileTemplates[i];
|
||||||
if ((curr_template->flags & nand_type) && (strncasecmp(fname, curr_template->name, 32) == 0))
|
if ((curr_template->flags & virtual_type) && ((strncasecmp(fname, curr_template->name, 32) == 0) ||
|
||||||
break;
|
(size && (curr_template->size == size)))) // search by size should be a last resort solution
|
||||||
else if (size && (curr_template->size == size)) //search by size should be a last resort solution
|
break;
|
||||||
break;
|
|
||||||
curr_template = NULL;
|
curr_template = NULL;
|
||||||
}
|
}
|
||||||
if (!curr_template) return false;
|
if (!curr_template) return false;
|
||||||
@ -82,11 +96,11 @@ bool FindVirtualFile(VirtualFile* vfile, const char* path, u32 size)
|
|||||||
if ((vfile->keyslot == 0x05) && !CheckSlot0x05Crypto())
|
if ((vfile->keyslot == 0x05) && !CheckSlot0x05Crypto())
|
||||||
return false; // keyslot 0x05 not properly set up
|
return false; // keyslot 0x05 not properly set up
|
||||||
if (vfile->flags & VFLAG_NAND_SIZE) {
|
if (vfile->flags & VFLAG_NAND_SIZE) {
|
||||||
if ((nand_src != NAND_SYSNAND) && (GetNandSizeSectors(NAND_SYSNAND) != GetNandSizeSectors(nand_src)))
|
if ((virtual_src != NAND_SYSNAND) && (GetNandSizeSectors(NAND_SYSNAND) != GetNandSizeSectors(virtual_src)))
|
||||||
return false; // EmuNAND/IMGNAND is too small
|
return false; // EmuNAND/IMGNAND is too small
|
||||||
vfile->size = GetNandSizeSectors(NAND_SYSNAND) * 0x200;
|
vfile->size = GetNandSizeSectors(NAND_SYSNAND) * 0x200;
|
||||||
}
|
}
|
||||||
vfile->flags |= nand_src;
|
vfile->flags |= virtual_src;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -99,37 +113,45 @@ int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u32 offset, u32 count,
|
|||||||
else if ((offset + count) > vfile->size)
|
else if ((offset + count) > vfile->size)
|
||||||
count = vfile->size - offset;
|
count = vfile->size - offset;
|
||||||
if (bytes_read) *bytes_read = count;
|
if (bytes_read) *bytes_read = count;
|
||||||
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
|
|
||||||
// simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src)
|
if (vfile->flags & VFLAG_ON_ALL) {
|
||||||
return ReadNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
|
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
|
||||||
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
|
// simple wrapper function for ReadNandSectors(u8* buffer, u32 sector, u32 count, u32 keyslot, u32 src)
|
||||||
} else { // nonaligned data -> -___-
|
return ReadNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
|
||||||
u8 l_buffer[0x200];
|
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
|
||||||
u32 nand_src = vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND);
|
} else { // nonaligned data -> -___-
|
||||||
u32 keyslot = vfile->keyslot;
|
u8 l_buffer[0x200];
|
||||||
int errorcode = 0;
|
u32 nand_src = vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND);
|
||||||
if (foffset % 0x200) { // handle misaligned offset
|
u32 keyslot = vfile->keyslot;
|
||||||
u32 offset_fix = 0x200 - (foffset % 0x200);
|
int errorcode = 0;
|
||||||
errorcode = ReadNandSectors(l_buffer, foffset / 0x200, 1, keyslot, nand_src);
|
if (foffset % 0x200) { // handle misaligned offset
|
||||||
if (errorcode != 0) return errorcode;
|
u32 offset_fix = 0x200 - (foffset % 0x200);
|
||||||
memcpy(buffer, l_buffer + 0x200 - offset_fix, min(offset_fix, count));
|
errorcode = ReadNandSectors(l_buffer, foffset / 0x200, 1, keyslot, nand_src);
|
||||||
if (count <= offset_fix) return 0;
|
if (errorcode != 0) return errorcode;
|
||||||
foffset += offset_fix;
|
memcpy(buffer, l_buffer + 0x200 - offset_fix, min(offset_fix, count));
|
||||||
buffer += offset_fix;
|
if (count <= offset_fix) return 0;
|
||||||
count -= offset_fix;
|
foffset += offset_fix;
|
||||||
} // foffset is now aligned and part of the data is read
|
buffer += offset_fix;
|
||||||
if (count >= 0x200) { // otherwise this is misaligned and will be handled below
|
count -= offset_fix;
|
||||||
errorcode = ReadNandSectors(buffer, foffset / 0x200, count / 0x200, keyslot, nand_src);
|
} // foffset is now aligned and part of the data is read
|
||||||
if (errorcode != 0) return errorcode;
|
if (count >= 0x200) { // otherwise this is misaligned and will be handled below
|
||||||
|
errorcode = ReadNandSectors(buffer, foffset / 0x200, count / 0x200, keyslot, nand_src);
|
||||||
|
if (errorcode != 0) return errorcode;
|
||||||
|
}
|
||||||
|
if (count % 0x200) { // handle misaligned count
|
||||||
|
u32 count_fix = count % 0x200;
|
||||||
|
errorcode = ReadNandSectors(l_buffer, (foffset + count) / 0x200, 1, keyslot, nand_src);
|
||||||
|
if (errorcode != 0) return errorcode;
|
||||||
|
memcpy(buffer + count - count_fix, l_buffer, count_fix);
|
||||||
|
}
|
||||||
|
return errorcode;
|
||||||
}
|
}
|
||||||
if (count % 0x200) { // handle misaligned count
|
} else if (vfile->flags & VFLAG_ON_MEMORY) {
|
||||||
u32 count_fix = count % 0x200;
|
memcpy(buffer, (u8*) foffset, count);
|
||||||
errorcode = ReadNandSectors(l_buffer, (foffset + count) / 0x200, 1, keyslot, nand_src);
|
return 0;
|
||||||
if (errorcode != 0) return errorcode;
|
|
||||||
memcpy(buffer + count - count_fix, l_buffer, count_fix);
|
|
||||||
}
|
|
||||||
return errorcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written)
|
int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32 count, u32* bytes_written)
|
||||||
@ -140,9 +162,17 @@ int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u32 offset, u32
|
|||||||
else if ((offset + count) > vfile->size)
|
else if ((offset + count) > vfile->size)
|
||||||
count = vfile->size - offset;
|
count = vfile->size - offset;
|
||||||
if (bytes_written) *bytes_written = count;
|
if (bytes_written) *bytes_written = count;
|
||||||
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
|
|
||||||
// simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest)
|
if (vfile->flags & VFLAG_ON_ALL) {
|
||||||
return WriteNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
|
if (!(foffset % 0x200) && !(count % 0x200)) { // aligned data -> simple case
|
||||||
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
|
// simple wrapper function for WriteNandSectors(const u8* buffer, u32 sector, u32 count, u32 keyslot, u32 dest)
|
||||||
} else return -1; // misaligned data -> not implemented (!!!)
|
return WriteNandSectors(buffer, foffset / 0x200, count / 0x200, vfile->keyslot,
|
||||||
|
vfile->flags & (VRT_SYSNAND | VRT_EMUNAND | VRT_IMGNAND));
|
||||||
|
} else return -1; // misaligned data -> not implemented (!!!)
|
||||||
|
} else if (vfile->flags & VFLAG_ON_MEMORY) {
|
||||||
|
memcpy((u8*) foffset, buffer, count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,13 @@
|
|||||||
#define VRT_SYSNAND NAND_SYSNAND
|
#define VRT_SYSNAND NAND_SYSNAND
|
||||||
#define VRT_EMUNAND NAND_EMUNAND
|
#define VRT_EMUNAND NAND_EMUNAND
|
||||||
#define VRT_IMGNAND NAND_IMGNAND
|
#define VRT_IMGNAND NAND_IMGNAND
|
||||||
|
#define VRT_MEMORY (1<<10)
|
||||||
|
|
||||||
static const char* virtualFileList[] = { // must have a match in virtualFileTemplates[]
|
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",
|
"twln.bin", "twlp.bin", "agbsave.bin", "firm0.bin", "firm1.bin", "ctrnand_fat.bin",
|
||||||
"nand.bin", "nand_minsize.bin", "nand_hdr.bin", "sector0x96.bin"
|
"ctrnand_full.bin", "nand.bin", "nand_minsize.bin", "nand_hdr.bin", "sector0x96.bin",
|
||||||
|
"itcm.dmp", "arm9internal.dmp", "vram.dmp", "dsp.dmp", "axiwram.dmp", "fcram.dmp",
|
||||||
|
"dtcm.dmp", "bootrom_unp.dmp"
|
||||||
};
|
};
|
||||||
static const u32 virtualFileList_size = sizeof(virtualFileList) / sizeof(char*);
|
static const u32 virtualFileList_size = sizeof(virtualFileList) / sizeof(char*);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user