mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Virtual VRAM drive, based on TAR
This commit is contained in:
parent
284fda27bc
commit
2d36460a02
@ -55,6 +55,8 @@ int DriveType(const char* path) {
|
|||||||
type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE;
|
type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE;
|
||||||
} else if (vsrc == VRT_CART) {
|
} else if (vsrc == VRT_CART) {
|
||||||
type = DRV_VIRTUAL | DRV_CART;
|
type = DRV_VIRTUAL | DRV_CART;
|
||||||
|
} else if (vsrc == VRT_VRAM) {
|
||||||
|
type = DRV_VIRTUAL | DRV_VRAM;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#define NORM_FS 10
|
#define NORM_FS 10
|
||||||
#define IMGN_FS 3 // image normal filesystems
|
#define IMGN_FS 3 // image normal filesystems
|
||||||
#define VIRT_FS 12
|
#define VIRT_FS 13
|
||||||
|
|
||||||
// primary drive types
|
// primary drive types
|
||||||
#define DRV_UNKNOWN (0<<0)
|
#define DRV_UNKNOWN (0<<0)
|
||||||
@ -23,10 +23,11 @@
|
|||||||
#define DRV_MEMORY (1UL<<10)
|
#define DRV_MEMORY (1UL<<10)
|
||||||
#define DRV_GAME (1UL<<11)
|
#define DRV_GAME (1UL<<11)
|
||||||
#define DRV_CART (1UL<<12)
|
#define DRV_CART (1UL<<12)
|
||||||
#define DRV_ALIAS (1UL<<13)
|
#define DRV_VRAM (1UL<<13)
|
||||||
#define DRV_BONUS (1UL<<14)
|
#define DRV_ALIAS (1UL<<14)
|
||||||
#define DRV_SEARCH (1UL<<15)
|
#define DRV_BONUS (1UL<<15)
|
||||||
#define DRV_STDFAT (1UL<<16) // standard FAT drive without limitations
|
#define DRV_SEARCH (1UL<<16)
|
||||||
|
#define DRV_STDFAT (1UL<<17) // standard FAT drive without limitations
|
||||||
|
|
||||||
#define FS_DRVNAME \
|
#define FS_DRVNAME \
|
||||||
"SDCARD", \
|
"SDCARD", \
|
||||||
@ -36,11 +37,12 @@
|
|||||||
"GAMECART", \
|
"GAMECART", \
|
||||||
"GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", \
|
"GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", \
|
||||||
"MEMORY VIRTUAL", \
|
"MEMORY VIRTUAL", \
|
||||||
|
"VRAM VIRTUAL", \
|
||||||
"NAND XORPADS", \
|
"NAND XORPADS", \
|
||||||
"LAST SEARCH" \
|
"LAST SEARCH" \
|
||||||
|
|
||||||
#define FS_DRVNUM \
|
#define FS_DRVNUM \
|
||||||
"0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "M:", "X:", "Z:"
|
"0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "M:", "V:", "X:", "Z:"
|
||||||
|
|
||||||
/** Function to identify the type of a drive **/
|
/** Function to identify the type of a drive **/
|
||||||
int DriveType(const char* path);
|
int DriveType(const char* path);
|
||||||
|
@ -19,5 +19,5 @@ typedef struct {
|
|||||||
u32 size_bss;
|
u32 size_bss;
|
||||||
u32 offset_smdh;
|
u32 offset_smdh;
|
||||||
u32 size_smdh;
|
u32 size_smdh;
|
||||||
u32 size_romfs_lv3;
|
u32 offset_romfs_lv3;
|
||||||
} __attribute__((packed)) ThreedsxHeader;
|
} __attribute__((packed)) ThreedsxHeader;
|
||||||
|
@ -235,7 +235,7 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, u32 curr_pan
|
|||||||
((drvtype & DRV_SDCARD) ? "SD" : (drvtype & DRV_RAMDRIVE) ? "RAMdrive" : (drvtype & DRV_GAME) ? "Game" :
|
((drvtype & DRV_SDCARD) ? "SD" : (drvtype & DRV_RAMDRIVE) ? "RAMdrive" : (drvtype & DRV_GAME) ? "Game" :
|
||||||
(drvtype & DRV_SYSNAND) ? "SysNAND" : (drvtype & DRV_EMUNAND) ? "EmuNAND" : (drvtype & DRV_IMAGE) ? "Image" :
|
(drvtype & DRV_SYSNAND) ? "SysNAND" : (drvtype & DRV_EMUNAND) ? "EmuNAND" : (drvtype & DRV_IMAGE) ? "Image" :
|
||||||
(drvtype & DRV_XORPAD) ? "XORpad" : (drvtype & DRV_MEMORY) ? "Memory" : (drvtype & DRV_ALIAS) ? "Alias" :
|
(drvtype & DRV_XORPAD) ? "XORpad" : (drvtype & DRV_MEMORY) ? "Memory" : (drvtype & DRV_ALIAS) ? "Alias" :
|
||||||
(drvtype & DRV_CART) ? "Gamecart" : (drvtype & DRV_SEARCH) ? "Search" : ""),
|
(drvtype & DRV_CART) ? "Gamecart" : (drvtype & DRV_VRAM) ? "VRAM" : (drvtype & DRV_SEARCH) ? "Search" : ""),
|
||||||
((drvtype & DRV_FAT) ? " FAT" : (drvtype & DRV_VIRTUAL) ? " Virtual" : ""));
|
((drvtype & DRV_FAT) ? " FAT" : (drvtype & DRV_VIRTUAL) ? " Virtual" : ""));
|
||||||
ResizeString(tempstr, drvstr, len_info / FONT_WIDTH_EXT, 8, false);
|
ResizeString(tempstr, drvstr, len_info / FONT_WIDTH_EXT, 8, false);
|
||||||
} else {
|
} else {
|
||||||
|
89
source/system/tar.c
Normal file
89
source/system/tar.c
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
|
||||||
|
u64 ReadAsciiOctal(char* num, u32 len) {
|
||||||
|
u64 res = 0;
|
||||||
|
|
||||||
|
if ((num[len-1] != '\0') && (num[len-1] != ' '))
|
||||||
|
return (u64) -1;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < (len-1); i++) {
|
||||||
|
res <<= 3;
|
||||||
|
if ((num[i] >= '0') && (num[i] < '8')) res |= (num[i] - '0');
|
||||||
|
else return (u64) -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 ValidateTarHeader(void* tardata, void* tardata_end) {
|
||||||
|
TarHeader* tar = tardata;
|
||||||
|
|
||||||
|
// available space
|
||||||
|
if ((u8*) tardata_end < (u8*) tardata + sizeof(TarHeader))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// filename prefix is not supported here
|
||||||
|
if (*(tar->fname_prefix)) return 1;
|
||||||
|
|
||||||
|
// ustar magic
|
||||||
|
if (strncmp(tar->magic, USTAR_MAGIC, 5) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// check filesize
|
||||||
|
u64 fsize_max = ((u8*) tardata_end - (u8*) tardata) - sizeof(TarHeader);
|
||||||
|
if (ReadAsciiOctal(tar->fsize, 12) > fsize_max)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// type can only be standard file or dir
|
||||||
|
if ((tar->ftype != '0') && (tar->ftype != '5'))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// checksum
|
||||||
|
u8* data = (u8*) tardata;
|
||||||
|
u64 checksum = 0;
|
||||||
|
for (u32 i = 0; i < sizeof(TarHeader); i++)
|
||||||
|
checksum += ((i < 148) || (i >= 156)) ? data[i] : (u64) ' ';
|
||||||
|
if (checksum != ReadAsciiOctal(tar->checksum, 7))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* GetTarFileInfo(void* tardata, char* fname, u64* fsize, bool* is_dir) {
|
||||||
|
// this assumes a valid TAR header
|
||||||
|
TarHeader* tar = tardata;
|
||||||
|
|
||||||
|
if (fname) snprintf(fname, 101, "%.100s", tar->fname);
|
||||||
|
if (fsize) *fsize = ReadAsciiOctal(tar->fsize, 12);
|
||||||
|
if (is_dir) *is_dir = (tar->ftype == '5');
|
||||||
|
|
||||||
|
return (void*) (tar + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* NextTarEntry(void* tardata, void* tardata_end) {
|
||||||
|
// this assumes a valid TAR header
|
||||||
|
TarHeader* tar = tardata;
|
||||||
|
u8* data = (u8*) tardata;
|
||||||
|
u64 fsize = ReadAsciiOctal(tar->fsize, 12);
|
||||||
|
|
||||||
|
data += sizeof(TarHeader) + align(fsize, 512);
|
||||||
|
if (ValidateTarHeader(data, tardata_end) != 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* FindTarFileInfo(void* tardata, void* tardata_end, const char* fname, u64* fsize, bool* is_dir) {
|
||||||
|
while (tardata && (tardata < tardata_end)) {
|
||||||
|
TarHeader* tar = tardata;
|
||||||
|
|
||||||
|
if (ValidateTarHeader(tardata, tardata_end) != 0) break;
|
||||||
|
ShowPrompt(false, "%s\n%s", tar->fname, fname);
|
||||||
|
if ((strncasecmp(tar->fname, fname, 100) == 0) && (tar->ftype == '0'))
|
||||||
|
return GetTarFileInfo(tardata, NULL, fsize, is_dir);
|
||||||
|
tardata = ((u8*) tardata) + sizeof(TarHeader) + align(ReadAsciiOctal(tar->fsize, 12), 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
35
source/system/tar.h
Normal file
35
source/system/tar.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define USTAR_MAGIC "ustar"
|
||||||
|
|
||||||
|
|
||||||
|
// see: https://en.wikipedia.org/wiki/Tar_(computing)
|
||||||
|
// all numeric values in ASCII / octal
|
||||||
|
typedef struct {
|
||||||
|
char fname[100];
|
||||||
|
char fmode[8];
|
||||||
|
char owner_id[8];
|
||||||
|
char group_id[8];
|
||||||
|
char fsize[12];
|
||||||
|
char last_modified[12];
|
||||||
|
char checksum[8];
|
||||||
|
char ftype;
|
||||||
|
char link_name[100];
|
||||||
|
// ustar extension
|
||||||
|
char magic[6]; // "ustar"
|
||||||
|
char version[2]; // "00"
|
||||||
|
char owner_name[32];
|
||||||
|
char group_name[32];
|
||||||
|
char dev_major[8];
|
||||||
|
char dev_minor[8];
|
||||||
|
char fname_prefix[155];
|
||||||
|
char unused[12];
|
||||||
|
} __attribute__((packed)) TarHeader;
|
||||||
|
|
||||||
|
|
||||||
|
u32 ValidateTarHeader(void* tardata, void* tardata_end);
|
||||||
|
void* GetTarFileInfo(void* tardata, char* fname, u64* fsize, bool* is_dir);
|
||||||
|
void* NextTarEntry(void* tardata, void* tardata_end);
|
||||||
|
void* FindTarFileInfo(void* tardata, void* tardata_end, const char* fname, u64* fsize, bool* is_dir);
|
31
source/system/vram0.h
Normal file
31
source/system/vram0.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "tar.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define VRAM0_OFFSET 0x18000000
|
||||||
|
#define VRAM0_LIMIT 0x00300000
|
||||||
|
|
||||||
|
#define TARDATA ((void*) VRAM0_OFFSET)
|
||||||
|
#define TARDATA_(off) ((void*) (u32) (VRAM0_OFFSET + (off)))
|
||||||
|
#define TARDATA_END TARDATA_(VRAM0_LIMIT)
|
||||||
|
|
||||||
|
|
||||||
|
#define CheckVram0Tar() \
|
||||||
|
(ValidateTarHeader(TARDATA, TARDATA_END) == 0)
|
||||||
|
|
||||||
|
#define FirstVTarEntry() \
|
||||||
|
TARDATA
|
||||||
|
|
||||||
|
#define OffsetVTarEntry(off) \
|
||||||
|
TARDATA_(off)
|
||||||
|
|
||||||
|
#define NextVTarEntry(tardata) \
|
||||||
|
NextTarEntry(tardata, TARDATA_END)
|
||||||
|
|
||||||
|
#define GetVTarFileInfo(tardata, fname, fsize, is_dir) \
|
||||||
|
GetTarFileInfo(tardata, fname, fsize, is_dir)
|
||||||
|
|
||||||
|
#define FindVTarFileInfo(fname, fsize, is_dir) \
|
||||||
|
FindTarFileInfo(TARDATA, TARDATA_END, fname, fsize, is_dir)
|
@ -827,7 +827,7 @@ bool ValidateText(const char* text, u32 len) {
|
|||||||
char c = text[i];
|
char c = text[i];
|
||||||
if ((c == '\r') && ((i+1) < len) && (text[i+1] != '\n')) return false; // CR without LF
|
if ((c == '\r') && ((i+1) < len) && (text[i+1] != '\n')) return false; // CR without LF
|
||||||
if ((c < 0x20) && (c != '\t') && (c != '\r') && (c != '\n')) return false; // illegal control char
|
if ((c < 0x20) && (c != '\t') && (c != '\r') && (c != '\n')) return false; // illegal control char
|
||||||
if ((c == 0x7F) || (c == 0xFF)) return false; // other illegal char
|
if (c == 0xFF) return false; // other illegal char
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -664,7 +664,7 @@ u64 InitVGameDrive(void) { // prerequisite: game file mounted as image
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 CheckVGameDrive(void) {
|
u64 CheckVGameDrive(void) {
|
||||||
if (vgame_type != GetMountState()) vgame_type = 0; // very basic sanity check
|
if (vgame_type != GetMountState()) vgame_type = 0; // very basic sanity check
|
||||||
return vgame_type;
|
return vgame_type;
|
||||||
}
|
}
|
||||||
@ -799,7 +799,6 @@ bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry) {
|
|||||||
|
|
||||||
bool ReadVGameDirLv3(VirtualFile* vfile, VirtualDir* vdir) {
|
bool ReadVGameDirLv3(VirtualFile* vfile, VirtualDir* vdir) {
|
||||||
vfile->name[0] = '\0';
|
vfile->name[0] = '\0';
|
||||||
BuildLv3Index(&lv3idx, romfslv3);
|
|
||||||
vfile->flags = VFLAG_LV3 | VFLAG_READONLY;
|
vfile->flags = VFLAG_LV3 | VFLAG_READONLY;
|
||||||
vfile->keyslot = ((offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch)) ?
|
vfile->keyslot = ((offset_ncch != (u64) -1) && NCCH_ENCRYPTED(ncch)) ?
|
||||||
0x2C : 0xFF; // actual keyslot may be different
|
0x2C : 0xFF; // actual keyslot may be different
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
|
|
||||||
u64 InitVGameDrive(void);
|
u64 InitVGameDrive(void);
|
||||||
u32 CheckVGameDrive(void);
|
u64 CheckVGameDrive(void);
|
||||||
|
|
||||||
bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry);
|
bool OpenVGameDir(VirtualDir* vdir, VirtualFile* ventry);
|
||||||
bool ReadVGameDir(VirtualFile* vfile, VirtualDir* vdir);
|
bool ReadVGameDir(VirtualFile* vfile, VirtualDir* vdir);
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#include "vtickdb.h"
|
#include "vtickdb.h"
|
||||||
#include "vkeydb.h"
|
#include "vkeydb.h"
|
||||||
#include "vcart.h"
|
#include "vcart.h"
|
||||||
|
#include "vvram.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char drv_letter;
|
char drv_letter;
|
||||||
@ -31,6 +32,8 @@ bool CheckVirtualDrive(const char* path) {
|
|||||||
u32 virtual_src = GetVirtualSource(path);
|
u32 virtual_src = GetVirtualSource(path);
|
||||||
if (virtual_src & (VRT_EMUNAND|VRT_IMGNAND))
|
if (virtual_src & (VRT_EMUNAND|VRT_IMGNAND))
|
||||||
return CheckVNandDrive(virtual_src); // check virtual NAND drive for EmuNAND / ImgNAND
|
return CheckVNandDrive(virtual_src); // check virtual NAND drive for EmuNAND / ImgNAND
|
||||||
|
else if (virtual_src & VRT_VRAM)
|
||||||
|
return CheckVVramDrive();
|
||||||
else if (virtual_src & VRT_GAME)
|
else if (virtual_src & VRT_GAME)
|
||||||
return CheckVGameDrive();
|
return CheckVGameDrive();
|
||||||
else if (virtual_src & VRT_TICKDB)
|
else if (virtual_src & VRT_TICKDB)
|
||||||
@ -55,6 +58,8 @@ bool ReadVirtualDir(VirtualFile* vfile, VirtualDir* vdir) {
|
|||||||
ret = ReadVKeyDbDir(vfile, vdir);
|
ret = ReadVKeyDbDir(vfile, vdir);
|
||||||
} else if (virtual_src & VRT_CART) {
|
} else if (virtual_src & VRT_CART) {
|
||||||
ret = ReadVCartDir(vfile, vdir);
|
ret = ReadVCartDir(vfile, vdir);
|
||||||
|
} else if (virtual_src & VRT_VRAM) {
|
||||||
|
ret = ReadVVramDir(vfile, vdir);
|
||||||
}
|
}
|
||||||
vfile->flags |= virtual_src; // add source flag
|
vfile->flags |= virtual_src; // add source flag
|
||||||
return ret;
|
return ret;
|
||||||
@ -111,8 +116,9 @@ bool GetVirtualFile(VirtualFile* vfile, const char* path) {
|
|||||||
if (!(vdir.flags & VFLAG_LV3)) { // standard method
|
if (!(vdir.flags & VFLAG_LV3)) { // standard method
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!ReadVirtualDir(vfile, &vdir)) return false;
|
if (!ReadVirtualDir(vfile, &vdir)) return false;
|
||||||
if ((!(vfile->flags & VRT_GAME) && (strncasecmp(name, vfile->name, 32) == 0)) ||
|
if ((!(vfile->flags & (VRT_GAME|VRT_VRAM)) && (strncasecmp(name, vfile->name, 32) == 0)) ||
|
||||||
((vfile->flags & VRT_GAME) && MatchVGameFilename(name, vfile, 256)))
|
((vfile->flags & VRT_GAME) && MatchVGameFilename(name, vfile, 256)) ||
|
||||||
|
((vfile->flags & VRT_VRAM) && MatchVVramFilename(name, vfile)))
|
||||||
break; // entry found
|
break; // entry found
|
||||||
}
|
}
|
||||||
} else { // use lv3 hashes for quicker search
|
} else { // use lv3 hashes for quicker search
|
||||||
@ -132,8 +138,10 @@ bool GetVirtualDir(VirtualDir* vdir, const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool GetVirtualFilename(char* name, const VirtualFile* vfile, u32 n_chars) {
|
bool GetVirtualFilename(char* name, const VirtualFile* vfile, u32 n_chars) {
|
||||||
if (!(vfile->flags & VRT_GAME)) strncpy(name, vfile->name, n_chars);
|
if (vfile->flags & VRT_GAME) return GetVGameFilename(name, vfile, n_chars);
|
||||||
else if (!GetVGameFilename(name, vfile, n_chars)) return false;
|
else if (vfile->flags & VRT_VRAM) return GetVVramFilename(name, vfile);
|
||||||
|
|
||||||
|
strncpy(name, vfile->name, n_chars);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -157,6 +165,8 @@ int ReadVirtualFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 coun
|
|||||||
return ReadVKeyDbFile(vfile, buffer, offset, count);
|
return ReadVKeyDbFile(vfile, buffer, offset, count);
|
||||||
} else if (vfile->flags & VRT_CART) {
|
} else if (vfile->flags & VRT_CART) {
|
||||||
return ReadVCartFile(vfile, buffer, offset, count);
|
return ReadVCartFile(vfile, buffer, offset, count);
|
||||||
|
} else if (vfile->flags & VRT_VRAM) {
|
||||||
|
return ReadVVramFile(vfile, buffer, offset, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@ -176,7 +186,7 @@ int WriteVirtualFile(const VirtualFile* vfile, const void* buffer, u64 offset, u
|
|||||||
return WriteVNandFile(vfile, buffer, offset, count);
|
return WriteVNandFile(vfile, buffer, offset, count);
|
||||||
} else if (vfile->flags & VRT_MEMORY) {
|
} else if (vfile->flags & VRT_MEMORY) {
|
||||||
return WriteVMemFile(vfile, buffer, offset, count);
|
return WriteVMemFile(vfile, buffer, offset, count);
|
||||||
} // no write support for virtual game / tickdb / keydb / cart files
|
} // no write support for virtual game / tickdb / keydb / cart / vram files
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -208,5 +218,7 @@ u64 GetVirtualDriveSize(const char* path) {
|
|||||||
return GetVKeyDbDriveSize();
|
return GetVKeyDbDriveSize();
|
||||||
else if (virtual_src & VRT_CART)
|
else if (virtual_src & VRT_CART)
|
||||||
return GetVCartDriveSize();
|
return GetVCartDriveSize();
|
||||||
|
else if (virtual_src & VRT_VRAM)
|
||||||
|
return GetVVramDriveSize();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,9 @@
|
|||||||
#define VRT_TICKDB (1UL<<6)
|
#define VRT_TICKDB (1UL<<6)
|
||||||
#define VRT_KEYDB (1UL<<7)
|
#define VRT_KEYDB (1UL<<7)
|
||||||
#define VRT_CART (1UL<<8)
|
#define VRT_CART (1UL<<8)
|
||||||
|
#define VRT_VRAM (1UL<<9)
|
||||||
|
|
||||||
#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_KEYDB|VRT_CART)
|
#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_KEYDB|VRT_CART|VRT_VRAM)
|
||||||
|
|
||||||
#define VFLAG_DIR (1UL<<10)
|
#define VFLAG_DIR (1UL<<10)
|
||||||
#define VFLAG_ROOT (1UL<<11)
|
#define VFLAG_ROOT (1UL<<11)
|
||||||
@ -23,7 +24,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \
|
#define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \
|
||||||
{'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_TICKDB}, {'C', VRT_CART}
|
{'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_TICKDB}, {'C', VRT_CART}, {'V', VRT_VRAM}
|
||||||
|
|
||||||
// virtual file flag (subject to change):
|
// virtual file flag (subject to change):
|
||||||
// bits 0...3 : reserved for NAND virtual sources and info
|
// bits 0...3 : reserved for NAND virtual sources and info
|
||||||
|
123
source/virtual/vvram.c
Normal file
123
source/virtual/vvram.c
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#include "vvram.h"
|
||||||
|
#include "vram0.h"
|
||||||
|
|
||||||
|
|
||||||
|
bool SplitTarFName(char* tar_fname, char** dir, char** name) {
|
||||||
|
u32 len = strnlen(tar_fname, 100 + 1);
|
||||||
|
if (!len || (len == 101)) return false;
|
||||||
|
|
||||||
|
// remove trailing slash
|
||||||
|
if (tar_fname[len-1] == '/') tar_fname[--len] = '\0';
|
||||||
|
|
||||||
|
// find last slash
|
||||||
|
char* slash = strrchr(tar_fname, '/');
|
||||||
|
|
||||||
|
// relative root dir entry
|
||||||
|
if (!slash) {
|
||||||
|
*name = tar_fname;
|
||||||
|
*dir = NULL;
|
||||||
|
} else {
|
||||||
|
*slash = '\0';
|
||||||
|
*name = slash + 1;
|
||||||
|
*dir = tar_fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CheckVVramDrive(void) {
|
||||||
|
return CheckVram0Tar();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ReadVVramDir(VirtualFile* vfile, VirtualDir* vdir) {
|
||||||
|
vfile->name[0] = '\0';
|
||||||
|
vfile->flags = VFLAG_READONLY;
|
||||||
|
vfile->keyslot = 0xFF;
|
||||||
|
|
||||||
|
|
||||||
|
// get current dir name
|
||||||
|
char curr_dir[100 + 1];
|
||||||
|
if (vdir->offset == (u64) -1) return false; // end of the dir?
|
||||||
|
else if (!vdir->offset) *curr_dir = '\0'; // relative root?
|
||||||
|
else {
|
||||||
|
// vdir->offset is offset of dir entry + 0x200
|
||||||
|
TarHeader* tar = (TarHeader*) OffsetVTarEntry(vdir->offset - 0x200);
|
||||||
|
strncpy(curr_dir, tar->fname, 100);
|
||||||
|
u32 len = strnlen(curr_dir, 100 + 1);
|
||||||
|
if (len == 101) return false; // path error
|
||||||
|
if (curr_dir[len-1] == '/') curr_dir[len-1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// using vdir index to signify the position limits us to 1TiB TARs
|
||||||
|
void* tardata = NULL;
|
||||||
|
if (vdir->index < 0) tardata = FirstVTarEntry();
|
||||||
|
else tardata = NextVTarEntry(OffsetVTarEntry(vdir->index << 9));
|
||||||
|
|
||||||
|
do {
|
||||||
|
TarHeader* tar = (TarHeader*) tardata;
|
||||||
|
char tar_fname[100 + 1];
|
||||||
|
char *name, *dir;
|
||||||
|
|
||||||
|
strncpy(tar_fname, tar->fname, 100);
|
||||||
|
if (!SplitTarFName(tar_fname, &dir, &name)) return false;
|
||||||
|
if ((!dir && !*curr_dir) || (dir && (strncmp(dir, curr_dir, 100) == 0))) break;
|
||||||
|
} while ((tardata = NextVTarEntry(tardata)));
|
||||||
|
|
||||||
|
// match found?
|
||||||
|
if (tardata) {
|
||||||
|
u64 fsize;
|
||||||
|
bool is_dir;
|
||||||
|
void* fdata = GetVTarFileInfo(tardata, NULL, &fsize, &is_dir);
|
||||||
|
|
||||||
|
vfile->offset = (u32) fdata - VRAM0_OFFSET;
|
||||||
|
vfile->size = fsize;
|
||||||
|
if (is_dir) vfile->flags |= VFLAG_DIR;
|
||||||
|
|
||||||
|
vdir->index = (vfile->offset >> 9) - 1;
|
||||||
|
} else { // not found
|
||||||
|
vdir->offset = (u64) -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ReadVVramFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count) {
|
||||||
|
if (vfile->flags & VFLAG_DIR) return -1;
|
||||||
|
void* fdata = (u8*) VRAM0_OFFSET + vfile->offset;
|
||||||
|
|
||||||
|
// range checks in virtual.c
|
||||||
|
memcpy(buffer, (u8*) fdata + offset, count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetVVramFilename(char* name, const VirtualFile* vfile) {
|
||||||
|
void* tardata = OffsetVTarEntry(vfile->offset - 0x200);
|
||||||
|
TarHeader* tar = (TarHeader*) tardata;
|
||||||
|
char tar_fname[100 + 1];
|
||||||
|
char *name_tmp, *dir;
|
||||||
|
|
||||||
|
strncpy(tar_fname, tar->fname, 100);
|
||||||
|
if (!SplitTarFName(tar_fname, &dir, &name_tmp)) return false;
|
||||||
|
strncpy(name, name_tmp, 100);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MatchVVramFilename(const char* name, const VirtualFile* vfile) {
|
||||||
|
void* tardata = OffsetVTarEntry(vfile->offset - 0x200);
|
||||||
|
TarHeader* tar = (TarHeader*) tardata;
|
||||||
|
char tar_fname[100 + 1];
|
||||||
|
char *name_tmp, *dir;
|
||||||
|
|
||||||
|
strncpy(tar_fname, tar->fname, 100);
|
||||||
|
if (!SplitTarFName(tar_fname, &dir, &name_tmp)) return false;
|
||||||
|
return (strncasecmp(name, name_tmp, 100) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 GetVVramDriveSize(void) {
|
||||||
|
return VRAM0_LIMIT;
|
||||||
|
}
|
12
source/virtual/vvram.h
Normal file
12
source/virtual/vvram.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "virtual.h"
|
||||||
|
|
||||||
|
bool CheckVVramDrive(void);
|
||||||
|
|
||||||
|
bool ReadVVramDir(VirtualFile* vfile, VirtualDir* vdir);
|
||||||
|
int ReadVVramFile(const VirtualFile* vfile, void* buffer, u64 offset, u64 count);
|
||||||
|
|
||||||
|
bool GetVVramFilename(char* name, const VirtualFile* vfile);
|
||||||
|
bool MatchVVramFilename(const char* name, const VirtualFile* vfile);
|
||||||
|
|
||||||
|
u64 GetVVramDriveSize(void);
|
Loading…
x
Reference in New Issue
Block a user