mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 21:52:48 +00:00
Working file copying routines
This commit is contained in:
parent
2a53ee0a5b
commit
df82754a6a
@ -264,22 +264,31 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) {
|
|||||||
return (lvl >= len);
|
return (lvl >= len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen)
|
bool ShowProgress(u64 current, u64 total, const char* opstr)
|
||||||
{
|
{
|
||||||
|
static u32 last_prog_width = 0;
|
||||||
const u32 bar_width = 240;
|
const u32 bar_width = 240;
|
||||||
const u32 bar_height = 12;
|
const u32 bar_height = 12;
|
||||||
const u32 bar_pos_x = (SCREEN_WIDTH_TOP - bar_width) / 2;
|
const u32 bar_pos_x = (SCREEN_WIDTH_TOP - bar_width) / 2;
|
||||||
const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2;
|
const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2 - 10;
|
||||||
const u32 text_pos_y = (SCREEN_HEIGHT / 2);
|
const u32 text_pos_y = bar_pos_y + bar_height + 2;
|
||||||
u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-4)) / total : 0;
|
u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-4)) / total : 0;
|
||||||
char tempstr[64];
|
char tempstr[64];
|
||||||
|
|
||||||
if (clearscreen) ClearScreenF(true, false, COLOR_STD_BG);
|
if (!current || last_prog_width > prog_width) {
|
||||||
DrawRectangleF(true, bar_pos_x, bar_pos_y, bar_width, bar_height, COLOR_DARKGREY);
|
ClearScreenF(true, false, COLOR_STD_BG);
|
||||||
DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, bar_width - 2, bar_height - 2, COLOR_STD_BG);
|
DrawRectangleF(true, bar_pos_x, bar_pos_y, bar_width, bar_height, COLOR_STD_FONT);
|
||||||
|
DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, bar_width - 2, bar_height - 2, COLOR_STD_BG);
|
||||||
|
}
|
||||||
DrawRectangleF(true, bar_pos_x + 2, bar_pos_y + 2, prog_width, bar_height - 4, COLOR_STD_FONT);
|
DrawRectangleF(true, bar_pos_x + 2, bar_pos_y + 2, prog_width, bar_height - 4, COLOR_STD_FONT);
|
||||||
|
|
||||||
ResizeString(tempstr, opstr, 28, 8, false);
|
ResizeString(tempstr, opstr, 28, 8, false);
|
||||||
DrawString(TOP_SCREEN0, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
|
DrawString(TOP_SCREEN0, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
|
||||||
DrawString(TOP_SCREEN1, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
|
DrawString(TOP_SCREEN1, tempstr, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG);
|
||||||
|
DrawString(TOP_SCREEN0, "(hold B to cancel)", bar_pos_x + 2, text_pos_y + 14, COLOR_STD_FONT, COLOR_STD_BG);
|
||||||
|
DrawString(TOP_SCREEN1, "(hold B to cancel)", bar_pos_x + 2, text_pos_y + 14, COLOR_STD_FONT, COLOR_STD_BG);
|
||||||
|
|
||||||
|
last_prog_width = prog_width;
|
||||||
|
|
||||||
|
return !(~HID_STATE & BUTTON_B);
|
||||||
}
|
}
|
||||||
|
@ -70,4 +70,4 @@ void FormatBytes(char* str, u64 bytes);
|
|||||||
|
|
||||||
bool ShowPrompt(bool ask, const char *format, ...);
|
bool ShowPrompt(bool ask, const char *format, ...);
|
||||||
bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
bool ShowUnlockSequence(u32 seqlvl, const char *format, ...);
|
||||||
void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen);
|
bool ShowProgress(u64 current, u64 total, const char* opstr);
|
||||||
|
43
source/fs.c
43
source/fs.c
@ -8,7 +8,7 @@ static FATFS* fs = (FATFS*)0x20316000;
|
|||||||
// this is the main buffer
|
// this is the main buffer
|
||||||
static u8* main_buffer = (u8*)0x21100000;
|
static u8* main_buffer = (u8*)0x21100000;
|
||||||
// this is the main buffer size
|
// this is the main buffer size
|
||||||
static size_t main_buffer_size = 128 * 1024;
|
static size_t main_buffer_size = 1 * 1024 * 1024;
|
||||||
|
|
||||||
// write permission level - careful with this
|
// write permission level - careful with this
|
||||||
static u32 write_permission_level = 1;
|
static u32 write_permission_level = 1;
|
||||||
@ -24,7 +24,7 @@ bool InitFS() {
|
|||||||
#endif
|
#endif
|
||||||
for (numfs = 0; numfs < 7; numfs++) {
|
for (numfs = 0; numfs < 7; numfs++) {
|
||||||
char fsname[8];
|
char fsname[8];
|
||||||
snprintf(fsname, 8, "%lu:", numfs);
|
snprintf(fsname, 7, "%lu:", numfs);
|
||||||
int res = f_mount(fs + numfs, fsname, 1);
|
int res = f_mount(fs + numfs, fsname, 1);
|
||||||
if (res != FR_OK) {
|
if (res != FR_OK) {
|
||||||
if (numfs >= 4) break;
|
if (numfs >= 4) break;
|
||||||
@ -115,35 +115,43 @@ bool FileCreate(const char* path, u8* data, u32 size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PathCopyWorker(char* dest, char* orig) {
|
bool PathCopyWorker(char* dest, char* orig) {
|
||||||
FILINFO fno;
|
FILINFO fno = {.lfname = NULL};
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
|
|
||||||
|
|
||||||
if (f_stat(dest, &fno) != FR_OK) return false; // destination directory does not exist
|
if (f_stat(dest, &fno) != FR_OK) return false; // destination directory does not exist
|
||||||
if (!(fno.fattrib & AM_DIR)) return false; // destination is not a directory (must be at this point)
|
if (!(fno.fattrib & AM_DIR)) return false; // destination is not a directory (must be at this point)
|
||||||
if (f_stat(orig, &fno) != FR_OK) return false; // origin does not exist
|
if (f_stat(orig, &fno) != FR_OK) return false; // origin does not exist
|
||||||
|
|
||||||
// get filename, build full destination path
|
// build full destination path (on top of destination directory)
|
||||||
char* oname = strrchr(orig, '/');
|
char* oname = strrchr(orig, '/');
|
||||||
char* dname = dest + strnlen(dest, 256);
|
char* dname = dest + strnlen(dest, 255);
|
||||||
if (oname == NULL) return false; // not a proper origin path
|
if (oname == NULL) return false; // not a proper origin path
|
||||||
oname++;
|
oname++;
|
||||||
*(dname++) = '/';
|
*(dname++) = '/';
|
||||||
strncpy(dname, oname, 256 - (dname - dest));
|
strncpy(dname, oname, 256 - (dname - dest));
|
||||||
|
|
||||||
|
// check if destination is part of or equal origin
|
||||||
|
if (strncmp(dest, orig, strnlen(orig, 255)) == 0) {
|
||||||
|
if ((dest[strnlen(orig, 255)] == '/') || (dest[strnlen(orig, 255)] == '\0'))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// check if destination exists
|
// check if destination exists
|
||||||
if (f_stat(dest, NULL) == FR_OK) {
|
if (f_stat(dest, NULL) == FR_OK) {
|
||||||
char tempstr[40];
|
char namestr[40];
|
||||||
TruncateString(tempstr, dest, 36, 8);
|
TruncateString(namestr, dest, 36, 8);
|
||||||
if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?"))
|
if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?", namestr))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// the copy process takes place here
|
// the copy process takes place here
|
||||||
ShowProgress(0, 0, orig, true);
|
if (!ShowProgress(0, 0, orig)) return false;
|
||||||
if (fno.fattrib & AM_DIR) { // processing folders...
|
if (fno.fattrib & AM_DIR) { // processing folders...
|
||||||
DIR pdir;
|
DIR pdir;
|
||||||
char* fname = orig + strnlen(orig, 256);
|
char* fname = orig + strnlen(orig, 256);
|
||||||
|
|
||||||
|
// create the destination folder if it does not already exist
|
||||||
if ((f_stat(dest, NULL) != FR_OK) && (f_mkdir(dest) != FR_OK))
|
if ((f_stat(dest, NULL) != FR_OK) && (f_mkdir(dest) != FR_OK))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -153,9 +161,7 @@ bool PathCopyWorker(char* dest, char* orig) {
|
|||||||
fno.lfname = fname;
|
fno.lfname = fname;
|
||||||
fno.lfsize = 256 - (fname - orig);
|
fno.lfsize = 256 - (fname - orig);
|
||||||
|
|
||||||
ShowPrompt(false, "Made:\n%s\n%s", orig, dest);
|
|
||||||
while (f_readdir(&pdir, &fno) == FR_OK) {
|
while (f_readdir(&pdir, &fno) == FR_OK) {
|
||||||
ShowPrompt(false, "Trying:\n%s\n%s", orig, dest);
|
|
||||||
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
|
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
|
||||||
continue; // filter out virtual entries
|
continue; // filter out virtual entries
|
||||||
if (fname[0] == 0)
|
if (fname[0] == 0)
|
||||||
@ -164,7 +170,6 @@ bool PathCopyWorker(char* dest, char* orig) {
|
|||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
} else if (!PathCopyWorker(dest, orig)) {
|
} else if (!PathCopyWorker(dest, orig)) {
|
||||||
ShowPrompt(false, "Failed:\n%s\n%s", orig, dest);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,20 +195,24 @@ bool PathCopyWorker(char* dest, char* orig) {
|
|||||||
for (size_t pos = 0; pos < fsize; pos += main_buffer_size) {
|
for (size_t pos = 0; pos < fsize; pos += main_buffer_size) {
|
||||||
UINT bytes_read = 0;
|
UINT bytes_read = 0;
|
||||||
UINT bytes_written = 0;
|
UINT bytes_written = 0;
|
||||||
ShowProgress(pos, fsize, orig, false);
|
|
||||||
f_read(&ofile, main_buffer, main_buffer_size, &bytes_read);
|
f_read(&ofile, main_buffer, main_buffer_size, &bytes_read);
|
||||||
|
if (!ShowProgress(pos + (bytes_read / 2), fsize, orig)) {
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
f_write(&dfile, main_buffer, bytes_read, &bytes_written);
|
f_write(&dfile, main_buffer, bytes_read, &bytes_written);
|
||||||
if (bytes_read != bytes_written) {
|
if (bytes_read != bytes_written) {
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShowProgress(1, 1, orig, false);
|
ShowProgress(1, 1, orig);
|
||||||
|
|
||||||
f_close(&ofile);
|
f_close(&ofile);
|
||||||
f_close(&dfile);
|
f_close(&dfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*(--dname) = '\0';
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,13 +220,13 @@ bool PathCopy(const char* destdir, const char* orig) {
|
|||||||
char fdpath[256]; // 256 is the maximum length of a full path
|
char fdpath[256]; // 256 is the maximum length of a full path
|
||||||
char fopath[256];
|
char fopath[256];
|
||||||
if (!CheckWritePermissions(destdir)) return false;
|
if (!CheckWritePermissions(destdir)) return false;
|
||||||
strncpy(fdpath, destdir, 256);
|
strncpy(fdpath, destdir, 255);
|
||||||
strncpy(fopath, orig, 256);
|
strncpy(fopath, orig, 255);
|
||||||
return PathCopyWorker(fdpath, fopath);
|
return PathCopyWorker(fdpath, fopath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathDeleteWorker(char* fpath) {
|
bool PathDeleteWorker(char* fpath) {
|
||||||
FILINFO fno;
|
FILINFO fno = {.lfname = NULL};
|
||||||
|
|
||||||
// this code handles directory content deletion
|
// this code handles directory content deletion
|
||||||
if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist
|
if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist
|
||||||
|
@ -85,6 +85,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c
|
|||||||
void DrawDirContents(DirStruct* contents, u32 cursor) {
|
void DrawDirContents(DirStruct* contents, u32 cursor) {
|
||||||
static u32 offset_disp = 0;
|
static u32 offset_disp = 0;
|
||||||
const int str_width = 39;
|
const int str_width = 39;
|
||||||
|
const u32 bar_height_min = 32;
|
||||||
|
const u32 bar_width = 2;
|
||||||
const u32 start_y = 2;
|
const u32 start_y = 2;
|
||||||
const u32 stp_y = 12;
|
const u32 stp_y = 12;
|
||||||
const u32 pos_x = 0;
|
const u32 pos_x = 0;
|
||||||
@ -114,9 +116,6 @@ void DrawDirContents(DirStruct* contents, u32 cursor) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (contents->n_entries > lines) { // draw position bar at the right
|
if (contents->n_entries > lines) { // draw position bar at the right
|
||||||
const u32 bar_height_min = 32;
|
|
||||||
const u32 bar_width = 2;
|
|
||||||
|
|
||||||
u32 bar_height = (lines * SCREEN_HEIGHT) / contents->n_entries;
|
u32 bar_height = (lines * SCREEN_HEIGHT) / contents->n_entries;
|
||||||
if (bar_height < bar_height_min) bar_height = bar_height_min;
|
if (bar_height < bar_height_min) bar_height = bar_height_min;
|
||||||
u32 bar_pos = ((u64) offset_disp * (SCREEN_HEIGHT - bar_height)) / (contents->n_entries - lines);
|
u32 bar_pos = ((u64) offset_disp * (SCREEN_HEIGHT - bar_height)) / (contents->n_entries - lines);
|
||||||
@ -124,7 +123,7 @@ void DrawDirContents(DirStruct* contents, u32 cursor) {
|
|||||||
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, bar_pos, COLOR_STD_BG);
|
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, bar_pos, COLOR_STD_BG);
|
||||||
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos + bar_height, bar_width, SCREEN_WIDTH_BOT - (bar_pos + bar_height), COLOR_STD_BG);
|
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos + bar_height, bar_width, SCREEN_WIDTH_BOT - (bar_pos + bar_height), COLOR_STD_BG);
|
||||||
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos, bar_width, bar_height, COLOR_SIDE_BAR);
|
DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, bar_pos, bar_width, bar_height, COLOR_SIDE_BAR);
|
||||||
}
|
} else DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, SCREEN_HEIGHT, COLOR_STD_BG);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GodMode() {
|
u32 GodMode() {
|
||||||
@ -217,10 +216,10 @@ u32 GodMode() {
|
|||||||
if (n_errors) ShowPrompt(false, "Failed deleting %u/%u path(s)", n_errors, n_marked);
|
if (n_errors) ShowPrompt(false, "Failed deleting %u/%u path(s)", n_errors, n_marked);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char namestr[20+1];
|
char namestr[36+1];
|
||||||
TruncateString(namestr, current_dir->entry[cursor].name, 20, 12);
|
TruncateString(namestr, current_dir->entry[cursor].name, 36, 12);
|
||||||
if ((ShowPrompt(true, "Delete \"%s\"?", namestr)) && !PathDelete(current_dir->entry[cursor].path))
|
if ((ShowPrompt(true, "Delete \"%s\"?", namestr)) && !PathDelete(current_dir->entry[cursor].path))
|
||||||
ShowPrompt(false, "Failed deleting \"%s\"", namestr);
|
ShowPrompt(false, "Failed deleting:\n%s", namestr);
|
||||||
}
|
}
|
||||||
GetDirContents(current_dir, current_path);
|
GetDirContents(current_dir, current_path);
|
||||||
if (cursor >= current_dir->n_entries)
|
if (cursor >= current_dir->n_entries)
|
||||||
@ -248,11 +247,11 @@ u32 GodMode() {
|
|||||||
if (ShowPrompt(true, promptstr)) {
|
if (ShowPrompt(true, promptstr)) {
|
||||||
for (u32 c = 0; c < clipboard->n_entries; c++) {
|
for (u32 c = 0; c < clipboard->n_entries; c++) {
|
||||||
if (!PathCopy(current_path, clipboard->entry[c].path)) {
|
if (!PathCopy(current_path, clipboard->entry[c].path)) {
|
||||||
char namestr[20+1];
|
char namestr[36+1];
|
||||||
TruncateString(namestr, clipboard->entry[c].name, 20, 12);
|
TruncateString(namestr, clipboard->entry[c].name, 36, 12);
|
||||||
if (c + 1 < clipboard->n_entries) {
|
if (c + 1 < clipboard->n_entries) {
|
||||||
if (!ShowPrompt(true, "Failed copying \"%s\"\nContinue?", namestr)) break;
|
if (!ShowPrompt(true, "Failed copying path:\n%s\nProcess remaining?", namestr)) break;
|
||||||
} else ShowPrompt(false, "Failed copying \"%s\"\n", namestr);
|
} else ShowPrompt(false, "Failed copying path:\n%s", namestr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user