mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 13:42:47 +00:00
Enabled basic file searching
This commit is contained in:
parent
b51af7ceb4
commit
dfd0a4e306
@ -34,7 +34,7 @@
|
|||||||
/ 2: Enable with LF-CRLF conversion. */
|
/ 2: Enable with LF-CRLF conversion. */
|
||||||
|
|
||||||
|
|
||||||
#define _USE_FIND 1
|
#define _USE_FIND 0
|
||||||
/* This option switches filtered directory read functions, f_findfirst() and
|
/* This option switches filtered directory read functions, f_findfirst() and
|
||||||
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
|
||||||
|
|
||||||
|
44
source/fatfs/store.c
Normal file
44
source/fatfs/store.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "store.h"
|
||||||
|
#include "ff.h"
|
||||||
|
|
||||||
|
#define STORE_BUFFER ((DirStruct*)0x21300000)
|
||||||
|
|
||||||
|
static bool is_stored = false;
|
||||||
|
|
||||||
|
bool IsStoredDrive(const char* path) {
|
||||||
|
return is_stored && (strncmp(path, "Z:", 3) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StoreDirContents(DirStruct* contents) {
|
||||||
|
memcpy(STORE_BUFFER, contents, sizeof(DirStruct));
|
||||||
|
is_stored = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetStoredDirContents(DirStruct* contents) {
|
||||||
|
// warning: this assumes the store buffer is filled with data that makes sense
|
||||||
|
DirStruct* stored = STORE_BUFFER;
|
||||||
|
u32 skip = 0;
|
||||||
|
|
||||||
|
// basic sanity checking
|
||||||
|
if (!is_stored || (stored->n_entries > MAX_ENTRIES)) return;
|
||||||
|
|
||||||
|
// copy available entries, remove missing from storage
|
||||||
|
for (u32 i = 0; i < stored->n_entries; i++) {
|
||||||
|
DirEntry* entry = &(stored->entry[i]);
|
||||||
|
if (strncmp(entry->name, "..", 3) == 0) continue; // disregard dotdot entry
|
||||||
|
if (f_stat(entry->path, NULL) != FR_OK) {
|
||||||
|
skip++; // remember this has to be removed from the stored struct
|
||||||
|
} else { // entry is valid
|
||||||
|
if (skip) { // move remaining entries to the left
|
||||||
|
stored->n_entries -= skip;
|
||||||
|
memmove(entry - skip, entry, (stored->n_entries - i) * sizeof(DirEntry));
|
||||||
|
entry -= skip;
|
||||||
|
skip = 0;
|
||||||
|
}
|
||||||
|
if (contents->n_entries < MAX_ENTRIES)
|
||||||
|
memcpy(&(contents->entry[contents->n_entries++]), entry, sizeof(DirEntry));
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stored->n_entries -= skip;
|
||||||
|
}
|
7
source/fatfs/store.h
Normal file
7
source/fatfs/store.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "fs.h"
|
||||||
|
|
||||||
|
bool IsStoredDrive(const char* path);
|
||||||
|
void StoreDirContents(DirStruct* contents);
|
||||||
|
void GetStoredDirContents(DirStruct* contents);
|
50
source/fs.c
50
source/fs.c
@ -2,6 +2,7 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "store.h"
|
||||||
#include "sha.h"
|
#include "sha.h"
|
||||||
#include "sdmmc.h"
|
#include "sdmmc.h"
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
@ -74,7 +75,7 @@ void DeinitSDCardFS() {
|
|||||||
int PathToNumFS(const char* path) {
|
int PathToNumFS(const char* path) {
|
||||||
int fsnum = *path - (int) '0';
|
int fsnum = *path - (int) '0';
|
||||||
if ((fsnum < 0) || (fsnum >= NORM_FS) || (path[1] != ':')) {
|
if ((fsnum < 0) || (fsnum >= NORM_FS) || (path[1] != ':')) {
|
||||||
if (!GetVirtualSource(path)) ShowPrompt(false, "Invalid path (%s)", path);
|
if (!GetVirtualSource(path) && !IsStoredDrive(path)) ShowPrompt(false, "Invalid path (%s)", path);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return fsnum;
|
return fsnum;
|
||||||
@ -949,6 +950,34 @@ void SortDirStruct(DirStruct* contents) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// inspired by http://www.geeksforgeeks.org/wildcard-character-matching/
|
||||||
|
bool MatchName(const char *pattern, const char *path) {
|
||||||
|
// handling non asterisk chars
|
||||||
|
for (; *pattern != '*'; pattern++, path++) {
|
||||||
|
if ((*pattern == '\0') && (*path == '\0')) {
|
||||||
|
return true; // end reached simultaneously, match found
|
||||||
|
} else if ((*pattern == '\0') || (*path == '\0')) {
|
||||||
|
return false; // end reached on only one, failure
|
||||||
|
} else if ((*pattern != '?') && (tolower(*pattern) != tolower(*path))) {
|
||||||
|
return false; // chars don't match, failure
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// handling the asterisk (matches one or more chars in path)
|
||||||
|
if ((*(pattern+1) == '?') || (*(pattern+1) == '*')) {
|
||||||
|
return false; // stupid user shenanigans, failure
|
||||||
|
} else if (*path == '\0') {
|
||||||
|
return false; // asterisk, but end reached on path, failure
|
||||||
|
} else if (*(pattern+1) == '\0') {
|
||||||
|
return true; // nothing after the asterisk, match found
|
||||||
|
} else { // we couldn't really go without recursion here
|
||||||
|
for (path++; *path != '\0'; path++) {
|
||||||
|
if (MatchName(pattern + 1, path)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool GetRootDirContentsWorker(DirStruct* contents) {
|
bool GetRootDirContentsWorker(DirStruct* contents) {
|
||||||
static const char* drvname[] = {
|
static const char* drvname[] = {
|
||||||
"SDCARD",
|
"SDCARD",
|
||||||
@ -986,11 +1015,12 @@ bool GetRootDirContentsWorker(DirStruct* contents) {
|
|||||||
return contents->n_entries;
|
return contents->n_entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path) {
|
bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path, const char* pattern) {
|
||||||
if (strchr(path, '/')) return false; // only top level paths
|
if (strchr(path, '/')) return false; // only top level paths
|
||||||
for (u32 n = 0; (n < virtualFileList_size) && (contents->n_entries < MAX_ENTRIES); n++) {
|
for (u32 n = 0; (n < virtualFileList_size) && (contents->n_entries < MAX_ENTRIES); n++) {
|
||||||
VirtualFile vfile;
|
VirtualFile vfile;
|
||||||
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
||||||
|
if (pattern && !MatchName(pattern, virtualFileList[n])) continue;
|
||||||
snprintf(entry->path, 256, "%s/%s", path, virtualFileList[n]);
|
snprintf(entry->path, 256, "%s/%s", path, virtualFileList[n]);
|
||||||
if (!FindVirtualFile(&vfile, entry->path, 0)) continue;
|
if (!FindVirtualFile(&vfile, entry->path, 0)) continue;
|
||||||
entry->name = entry->path + strnlen(path, 256) + 1;
|
entry->name = entry->path + strnlen(path, 256) + 1;
|
||||||
@ -1003,7 +1033,7 @@ bool GetVirtualDirContentsWorker(DirStruct* contents, const char* path) {
|
|||||||
return true; // not much we can check here
|
return true; // not much we can check here
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool recursive) {
|
bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, const char* pattern, bool recursive) {
|
||||||
DIR pdir;
|
DIR pdir;
|
||||||
FILINFO fno;
|
FILINFO fno;
|
||||||
char* fname = fpath + strnlen(fpath, fnsize - 1);
|
char* fname = fpath + strnlen(fpath, fnsize - 1);
|
||||||
@ -1020,7 +1050,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
|||||||
if (fno.fname[0] == 0) {
|
if (fno.fname[0] == 0) {
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else if (!pattern || MatchName(pattern, fname)) {
|
||||||
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
DirEntry* entry = &(contents->entry[contents->n_entries]);
|
||||||
strncpy(entry->path, fpath, 256);
|
strncpy(entry->path, fpath, 256);
|
||||||
entry->name = entry->path + (fname - fpath);
|
entry->name = entry->path + (fname - fpath);
|
||||||
@ -1037,7 +1067,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (recursive && (fno.fattrib & AM_DIR)) {
|
if (recursive && (fno.fattrib & AM_DIR)) {
|
||||||
if (!GetDirContentsWorker(contents, fpath, fnsize, recursive))
|
if (!GetDirContentsWorker(contents, fpath, fnsize, pattern, recursive))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1046,7 +1076,7 @@ bool GetDirContentsWorker(DirStruct* contents, char* fpath, int fnsize, bool rec
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetDirContents(DirStruct* contents, const char* path) {
|
void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive) {
|
||||||
contents->n_entries = 0;
|
contents->n_entries = 0;
|
||||||
if (!(*path)) { // root directory
|
if (!(*path)) { // root directory
|
||||||
if (!GetRootDirContentsWorker(contents))
|
if (!GetRootDirContentsWorker(contents))
|
||||||
@ -1060,18 +1090,22 @@ void GetDirContents(DirStruct* contents, const char* path) {
|
|||||||
contents->entry->size = 0;
|
contents->entry->size = 0;
|
||||||
contents->n_entries = 1;
|
contents->n_entries = 1;
|
||||||
if (GetVirtualSource(path)) {
|
if (GetVirtualSource(path)) {
|
||||||
if (!GetVirtualDirContentsWorker(contents, path))
|
if (!GetVirtualDirContentsWorker(contents, path, pattern))
|
||||||
contents->n_entries = 0;
|
contents->n_entries = 0;
|
||||||
} else {
|
} else {
|
||||||
char fpath[256]; // 256 is the maximum length of a full path
|
char fpath[256]; // 256 is the maximum length of a full path
|
||||||
strncpy(fpath, path, 256);
|
strncpy(fpath, path, 256);
|
||||||
if (!GetDirContentsWorker(contents, fpath, 256, false))
|
if (!GetDirContentsWorker(contents, fpath, 256, pattern, recursive))
|
||||||
contents->n_entries = 0;
|
contents->n_entries = 0;
|
||||||
}
|
}
|
||||||
SortDirStruct(contents);
|
SortDirStruct(contents);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetDirContents(DirStruct* contents, const char* path) {
|
||||||
|
SearchDirContents(contents, path, NULL, false);
|
||||||
|
}
|
||||||
|
|
||||||
uint64_t GetFreeSpace(const char* path)
|
uint64_t GetFreeSpace(const char* path)
|
||||||
{
|
{
|
||||||
DWORD free_clusters;
|
DWORD free_clusters;
|
||||||
|
@ -90,6 +90,9 @@ bool DirCreate(const char* cpath, const char* dirname);
|
|||||||
/** Create a screenshot of the current framebuffer **/
|
/** Create a screenshot of the current framebuffer **/
|
||||||
void CreateScreenshot();
|
void CreateScreenshot();
|
||||||
|
|
||||||
|
/** Search under a given path **/
|
||||||
|
void SearchDirContents(DirStruct* contents, const char* path, const char* pattern, bool recursive);
|
||||||
|
|
||||||
/** Get directory content under a given path **/
|
/** Get directory content under a given path **/
|
||||||
void GetDirContents(DirStruct* contents, const char* path);
|
void GetDirContents(DirStruct* contents, const char* path);
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
#include "virtual.h"
|
#include "virtual.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
#include "store.h"
|
||||||
|
|
||||||
#define VERSION "0.6.2"
|
#define VERSION "0.6.3"
|
||||||
|
|
||||||
#define N_PANES 2
|
#define N_PANES 2
|
||||||
#define IMG_DRV "789I"
|
#define IMG_DRV "789I"
|
||||||
@ -544,13 +545,26 @@ u32 GodMode() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// basic navigation commands
|
// basic navigation commands
|
||||||
if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // one level up
|
if ((pad_state & BUTTON_A) && (curr_entry->type != T_FILE) && (curr_entry->type != T_DOTDOT)) { // for dirs
|
||||||
strncpy(current_path, curr_entry->path, 256);
|
if (switched) { // search directory
|
||||||
GetDirContents(current_dir, current_path);
|
char searchstr[256];
|
||||||
if (*current_path && (current_dir->n_entries > 1)) {
|
char namestr[20+1];
|
||||||
cursor = 1;
|
snprintf(searchstr, 256, "*.*");
|
||||||
scroll = 0;
|
TruncateString(namestr, curr_entry->name, 20, 8);
|
||||||
} else cursor = 0;
|
if (ShowStringPrompt(searchstr, 256, "Search %s?\nEnter search below.", namestr)) {
|
||||||
|
ShowString("Searching path, please wait...");
|
||||||
|
snprintf(current_path, 256, "Z:");
|
||||||
|
SearchDirContents(current_dir, curr_entry->path, searchstr, true);
|
||||||
|
StoreDirContents(current_dir);
|
||||||
|
}
|
||||||
|
} else { // one level up
|
||||||
|
strncpy(current_path, curr_entry->path, 256);
|
||||||
|
GetDirContents(current_dir, current_path);
|
||||||
|
if (*current_path && (current_dir->n_entries > 1)) {
|
||||||
|
cursor = 1;
|
||||||
|
scroll = 0;
|
||||||
|
} else cursor = 0;
|
||||||
|
}
|
||||||
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
|
} else if ((pad_state & BUTTON_A) && (curr_entry->type == T_FILE)) { // process a file
|
||||||
u32 file_type = IdentifyImage(curr_entry->path);
|
u32 file_type = IdentifyImage(curr_entry->path);
|
||||||
bool injectable = (clipboard->n_entries == 1) &&
|
bool injectable = (clipboard->n_entries == 1) &&
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
#include "nand.h"
|
#include "nand.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
#define NAND_BUFFER ((u8*)0x21300000)
|
#define NAND_BUFFER ((u8*)0x21400000)
|
||||||
#define NAND_BUFFER_SIZE (0x100000) // must be multiple of 0x200
|
#define NAND_BUFFER_SIZE (0x100000) // must be multiple of 0x200
|
||||||
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800)
|
#define NAND_MIN_SECTORS ((GetUnitPlatform() == PLATFORM_N3DS) ? 0x26C000 : 0x1D7800)
|
||||||
|
|
||||||
|
@ -440,7 +440,7 @@ bool ShowInputPrompt(char* inputstr, u32 max_size, u32 resize, const char* alpha
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...) {
|
bool ShowStringPrompt(char* inputstr, u32 max_size, const char *format, ...) {
|
||||||
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~!@#$%&0123456789=+-_.";
|
const char* alphabet = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz(){}[]'`^,~*?!@#$%&0123456789=+-_.";
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
va_list va;
|
va_list va;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user