239 lines
8.9 KiB
C
Raw Normal View History

2016-12-10 15:32:03 +01:00
#include "fsdrive.h"
#include "fsgame.h"
2016-12-10 15:32:03 +01:00
#include "fsinit.h"
#include "virtual.h"
#include "sddata.h"
#include "image.h"
#include "ui.h"
2017-06-06 21:14:19 +02:00
#include "vff.h"
2016-12-10 15:32:03 +01:00
// last search pattern, path & mode
2016-12-10 15:32:03 +01:00
static char search_pattern[256] = { 0 };
static char search_path[256] = { 0 };
static bool search_title_mode = false;
2016-12-10 15:32:03 +01:00
int DriveType(const char* path) {
int type = DRV_UNKNOWN;
int pdrv = GetMountedFSNum(path);
if (CheckAliasDrive(path)) {
2017-02-15 16:34:25 +01:00
type = DRV_FAT | DRV_ALIAS | ((*path == 'A') ? DRV_SYSNAND : DRV_EMUNAND);
2016-12-10 15:32:03 +01:00
} else if (*search_pattern && *search_path && (strncmp(path, "Z:", 3) == 0)) {
type = DRV_SEARCH;
} else if ((pdrv >= 0) && (pdrv < NORM_FS)) {
if (pdrv == 0) {
type = DRV_FAT | DRV_SDCARD | DRV_STDFAT;
} else if ((pdrv == 8) && !(GetMountState() & IMG_NAND)) {
type = DRV_FAT | DRV_SYSNAND | DRV_BONUS | DRV_STDFAT;
} else if ((pdrv == 9) && !(GetMountState() & IMG_NAND)) {
2016-12-10 15:32:03 +01:00
type = DRV_FAT | DRV_RAMDRIVE | DRV_STDFAT;
2017-02-15 16:34:25 +01:00
} else if (pdrv == 1) {
type = DRV_FAT | DRV_SYSNAND | DRV_CTRNAND | DRV_STDFAT;
} else if ((pdrv == 2) || (pdrv == 3)) {
type = DRV_FAT | DRV_SYSNAND | DRV_TWLNAND | DRV_STDFAT;
} else if (pdrv == 4) {
type = DRV_FAT | DRV_EMUNAND | DRV_CTRNAND | DRV_STDFAT;
} else if ((pdrv == 5) || (pdrv == 6)) {
type = DRV_FAT | DRV_EMUNAND | DRV_TWLNAND | DRV_STDFAT;
2016-12-10 15:32:03 +01:00
} else if ((pdrv >= 7) && (pdrv <= 9) &&
(GetMountState() & (IMG_FAT|IMG_NAND))) {
2016-12-10 15:32:03 +01:00
type = DRV_FAT | DRV_IMAGE | DRV_STDFAT;
}
} else if (CheckVirtualDrive(path)) {
int vsrc = GetVirtualSource(path);
if (vsrc == VRT_SYSNAND) {
type = DRV_VIRTUAL | DRV_SYSNAND;
} else if (vsrc == VRT_EMUNAND) {
type = DRV_VIRTUAL | DRV_EMUNAND;
} else if (vsrc == VRT_IMGNAND) {
type = DRV_VIRTUAL | DRV_IMAGE;
} else if (vsrc == VRT_XORPAD) {
type = DRV_VIRTUAL | DRV_XORPAD;
} else if (vsrc == VRT_MEMORY) {
type = DRV_VIRTUAL | DRV_MEMORY;
2017-04-18 17:27:44 +02:00
} else if ((vsrc == VRT_GAME) || (vsrc == VRT_KEYDB) || (vsrc == VRT_TICKDB)) {
2017-02-11 16:52:36 +01:00
type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE;
2017-01-13 14:20:42 +01:00
} else if (vsrc == VRT_CART) {
type = DRV_VIRTUAL | DRV_CART;
2017-10-30 14:46:37 +01:00
} else if (vsrc == VRT_VRAM) {
type = DRV_VIRTUAL | DRV_VRAM;
2016-12-10 15:32:03 +01:00
}
}
return type;
}
void SetFSSearch(const char* pattern, const char* path, bool mode) {
2016-12-10 15:32:03 +01:00
if (pattern && path) {
strncpy(search_pattern, pattern, 256);
search_pattern[255] = '\0';
2016-12-10 15:32:03 +01:00
strncpy(search_path, path, 256);
search_path[255] = '\0';
search_title_mode = mode;
2016-12-10 15:32:03 +01:00
} else *search_pattern = *search_path = '\0';
}
bool GetFATVolumeLabel(const char* drv, char* label) {
return (f_getlabel(drv, label, NULL) == FR_OK);
}
2016-12-10 15:32:03 +01:00
bool GetRootDirContentsWorker(DirStruct* contents) {
static const char* drvname[] = { FS_DRVNAME };
static const char* drvnum[] = { FS_DRVNUM };
u32 n_entries = 0;
char sdlabel[16];
if (!GetFATVolumeLabel("0:", sdlabel))
snprintf(sdlabel, 16, "NOLABEL");
2016-12-10 15:32:03 +01:00
// virtual root objects hacked in
2017-02-10 15:04:31 +01:00
for (u32 i = 0; (i < NORM_FS+VIRT_FS) && (n_entries < MAX_DIR_ENTRIES); i++) {
2016-12-10 15:32:03 +01:00
DirEntry* entry = &(contents->entry[n_entries]);
2017-02-10 15:04:31 +01:00
if (!DriveType(drvnum[i])) continue; // drive not available
entry->p_name = 4;
entry->name = entry->path + entry->p_name;
2016-12-10 15:32:03 +01:00
memset(entry->path, 0x00, 64);
snprintf(entry->path, 4, "%s", drvnum[i]);
if ((*(drvnum[i]) >= '7') && (*(drvnum[i]) <= '9') && !(GetMountState() & IMG_NAND)) // Drive 7...9 handling
snprintf(entry->name, 32, "[%s] %s", drvnum[i],
(*(drvnum[i]) == '7') ? "FAT IMAGE" :
(*(drvnum[i]) == '8') ? "BONUS DRIVE" :
(*(drvnum[i]) == '9') ? "RAMDRIVE" : "UNK");
2017-02-10 15:04:31 +01:00
else if (*(drvnum[i]) == 'G') // Game drive special handling
snprintf(entry->name, 32, "[%s] %s %s", drvnum[i],
(GetMountState() & GAME_CIA ) ? "CIA" :
(GetMountState() & GAME_NCSD ) ? "NCSD" :
(GetMountState() & GAME_NCCH ) ? "NCCH" :
(GetMountState() & GAME_EXEFS) ? "EXEFS" :
(GetMountState() & GAME_ROMFS) ? "ROMFS" :
(GetMountState() & GAME_NDS ) ? "NDS" :
(GetMountState() & SYS_FIRM ) ? "FIRM" :
(GetMountState() & GAME_TAD ) ? "DSIWARE" : "UNK", drvname[i]);
else if (*(drvnum[i]) == '0') // SD card handling
snprintf(entry->name, 32, "[%s] %s (%s)", drvnum[i], drvname[i], sdlabel);
else snprintf(entry->name, 32, "[%s] %s", drvnum[i], drvname[i]);
2016-12-10 15:32:03 +01:00
entry->size = GetTotalSpace(entry->path);
entry->type = T_ROOT;
entry->marked = 0;
n_entries++;
}
contents->n_entries = n_entries;
return contents->n_entries;
}
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, const char* pattern, bool recursive) {
DIR pdir;
FILINFO fno;
char* fname = fpath + strnlen(fpath, fnsize - 1);
bool ret = false;
2017-06-06 21:14:19 +02:00
if (fvx_opendir(&pdir, fpath) != FR_OK)
2016-12-10 15:32:03 +01:00
return false;
if (*(fname-1) != '/') *(fname++) = '/';
2016-12-10 15:32:03 +01:00
2017-06-06 21:14:19 +02:00
while (fvx_readdir(&pdir, &fno) == FR_OK) {
2016-12-10 15:32:03 +01:00
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
continue; // filter out virtual entries
2017-12-18 16:53:25 +01:00
#ifdef HIDE_HIDDEN
if (fno.fattrib & AM_HID)
continue; // filter out hidden entries
#endif
2016-12-10 15:32:03 +01:00
strncpy(fname, fno.fname, (fnsize - 1) - (fname - fpath));
if (fno.fname[0] == 0) {
ret = true;
break;
2017-06-06 21:14:19 +02:00
} else if (!pattern || (fvx_match_name(fname, pattern) == FR_OK)) {
2016-12-10 15:32:03 +01:00
DirEntry* entry = &(contents->entry[contents->n_entries]);
strncpy(entry->path, fpath, 256);
entry->path[255] = '\0';
entry->p_name = fname - fpath;
entry->name = entry->path + entry->p_name;
2016-12-10 15:32:03 +01:00
if (fno.fattrib & AM_DIR) {
entry->type = T_DIR;
entry->size = 0;
} else {
entry->type = T_FILE;
entry->size = fno.fsize;
}
entry->marked = 0;
if (!recursive || (entry->type != T_DIR)) {
if (++(contents->n_entries) >= MAX_DIR_ENTRIES) {
ret = true; // Too many entries, still okay if we stop here
break;
}
2016-12-10 15:32:03 +01:00
}
}
if (recursive && (fno.fattrib & AM_DIR)) {
if (!GetDirContentsWorker(contents, fpath, fnsize, pattern, recursive))
break;
}
}
2017-06-06 21:14:19 +02:00
fvx_closedir(&pdir);
2016-12-10 15:32:03 +01:00
return ret;
}
void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive) {
contents->n_entries = 0;
if (!(*path)) { // root directory
if (!GetRootDirContentsWorker(contents))
contents->n_entries = 0; // not required, but so what?
} else {
// create virtual '..' entry
DirEntry* entry = (DirEntry*) &(contents->entry);
entry->p_name = 4;
entry->name = entry->path + entry->p_name;
strncpy(entry->path, "*?*", 4);
strncpy(entry->name, "..", 4);
entry->type = T_DOTDOT;
entry->size = 0;
2016-12-10 15:32:03 +01:00
contents->n_entries = 1;
// search the path
char fpath[256]; // 256 is the maximum length of a full path
strncpy(fpath, path, 256);
fpath[255] = '\0';
2017-06-06 21:14:19 +02:00
if (!GetDirContentsWorker(contents, fpath, 256, pattern, recursive))
contents->n_entries = 0;
2016-12-10 15:32:03 +01:00
}
}
void GetDirContents(DirStruct* contents, const char* path) {
if (*search_path && (DriveType(path) & DRV_SEARCH)) {
2016-12-10 15:32:03 +01:00
ShowString("Searching, please wait...");
SearchDirContents(contents, search_path, search_pattern, true);
if (search_title_mode) SetDirGoodNames(contents);
2016-12-10 15:32:03 +01:00
ClearScreenF(true, false, COLOR_STD_BG);
} else SearchDirContents(contents, path, NULL, false);
if (*path) SortDirStruct(contents);
2016-12-10 15:32:03 +01:00
}
uint64_t GetFreeSpace(const char* path)
{
DWORD free_clusters;
FATFS* fsptr;
char fsname[4] = { '\0' };
int pdrv = GetMountedFSNum(path);
FATFS* fsobj = GetMountedFSObject(path);
if ((pdrv < 0) || !fsobj) return 0;
snprintf(fsname, 3, "%i:", pdrv);
if (f_getfree(fsname, &free_clusters, &fsptr) != FR_OK)
return 0;
2017-08-15 03:12:33 +02:00
return (uint64_t) free_clusters * fsobj->csize * FF_MAX_SS;
2016-12-10 15:32:03 +01:00
}
uint64_t GetTotalSpace(const char* path)
{
FATFS* fsobj = GetMountedFSObject(path);
2017-08-15 03:12:33 +02:00
return (fsobj) ? ((uint64_t) (fsobj->n_fatent - 2) * fsobj->csize * FF_MAX_SS) :
2017-01-17 23:24:46 +01:00
GetVirtualDriveSize(path);
2016-12-10 15:32:03 +01:00
}
uint64_t GetPartitionOffsetSector(const char* path)
{
FATFS* fsobj = GetMountedFSObject(path);
return (fsobj) ? (uint64_t) fsobj->volbase : 0;
}