diff --git a/source/draw.c b/source/draw.c index 966c919..5743a76 100644 --- a/source/draw.c +++ b/source/draw.c @@ -264,22 +264,31 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { 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_height = 12; const u32 bar_pos_x = (SCREEN_WIDTH_TOP - bar_width) / 2; - const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2; - const u32 text_pos_y = (SCREEN_HEIGHT / 2); + const u32 bar_pos_y = (SCREEN_HEIGHT / 2) - bar_height - 2 - 10; + const u32 text_pos_y = bar_pos_y + bar_height + 2; u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-4)) / total : 0; char tempstr[64]; - if (clearscreen) ClearScreenF(true, false, COLOR_STD_BG); - DrawRectangleF(true, bar_pos_x, bar_pos_y, bar_width, bar_height, COLOR_DARKGREY); - DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, bar_width - 2, bar_height - 2, COLOR_STD_BG); + if (!current || last_prog_width > prog_width) { + ClearScreenF(true, false, 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); ResizeString(tempstr, opstr, 28, 8, false); 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_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); } diff --git a/source/draw.h b/source/draw.h index 184705e..08f909e 100644 --- a/source/draw.h +++ b/source/draw.h @@ -70,4 +70,4 @@ void FormatBytes(char* str, u64 bytes); bool ShowPrompt(bool ask, 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); diff --git a/source/fs.c b/source/fs.c index de7fbc3..97f4267 100644 --- a/source/fs.c +++ b/source/fs.c @@ -8,7 +8,7 @@ static FATFS* fs = (FATFS*)0x20316000; // this is the main buffer static u8* main_buffer = (u8*)0x21100000; // 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 static u32 write_permission_level = 1; @@ -24,7 +24,7 @@ bool InitFS() { #endif for (numfs = 0; numfs < 7; numfs++) { char fsname[8]; - snprintf(fsname, 8, "%lu:", numfs); + snprintf(fsname, 7, "%lu:", numfs); int res = f_mount(fs + numfs, fsname, 1); if (res != FR_OK) { if (numfs >= 4) break; @@ -115,35 +115,43 @@ bool FileCreate(const char* path, u8* data, u32 size) { } bool PathCopyWorker(char* dest, char* orig) { - FILINFO fno; + FILINFO fno = {.lfname = NULL}; bool ret = false; + 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 (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* dname = dest + strnlen(dest, 256); + char* dname = dest + strnlen(dest, 255); if (oname == NULL) return false; // not a proper origin path oname++; *(dname++) = '/'; 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 if (f_stat(dest, NULL) == FR_OK) { - char tempstr[40]; - TruncateString(tempstr, dest, 36, 8); - if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?")) + char namestr[40]; + TruncateString(namestr, dest, 36, 8); + if (!ShowPrompt(true, "Destination already exists:\n%s\nOverwrite existing file(s)?", namestr)) return false; } // 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... DIR pdir; 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)) return false; @@ -153,9 +161,7 @@ bool PathCopyWorker(char* dest, char* orig) { fno.lfname = fname; fno.lfsize = 256 - (fname - orig); - ShowPrompt(false, "Made:\n%s\n%s", orig, dest); 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)) continue; // filter out virtual entries if (fname[0] == 0) @@ -164,7 +170,6 @@ bool PathCopyWorker(char* dest, char* orig) { ret = true; break; } else if (!PathCopyWorker(dest, orig)) { - ShowPrompt(false, "Failed:\n%s\n%s", orig, dest); break; } } @@ -189,21 +194,25 @@ bool PathCopyWorker(char* dest, char* orig) { ret = true; for (size_t pos = 0; pos < fsize; pos += main_buffer_size) { UINT bytes_read = 0; - UINT bytes_written = 0; - ShowProgress(pos, fsize, orig, false); + UINT bytes_written = 0; 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); if (bytes_read != bytes_written) { ret = false; break; } } - ShowProgress(1, 1, orig, false); + ShowProgress(1, 1, orig); f_close(&ofile); f_close(&dfile); } + *(--dname) = '\0'; 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 fopath[256]; if (!CheckWritePermissions(destdir)) return false; - strncpy(fdpath, destdir, 256); - strncpy(fopath, orig, 256); + strncpy(fdpath, destdir, 255); + strncpy(fopath, orig, 255); return PathCopyWorker(fdpath, fopath); } bool PathDeleteWorker(char* fpath) { - FILINFO fno; + FILINFO fno = {.lfname = NULL}; // this code handles directory content deletion if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist diff --git a/source/godmode.c b/source/godmode.c index 40a1b1e..1f766b5 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -85,6 +85,8 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c void DrawDirContents(DirStruct* contents, u32 cursor) { static u32 offset_disp = 0; const int str_width = 39; + const u32 bar_height_min = 32; + const u32 bar_width = 2; const u32 start_y = 2; const u32 stp_y = 12; const u32 pos_x = 0; @@ -113,10 +115,7 @@ void DrawDirContents(DirStruct* contents, u32 cursor) { pos_y += stp_y; } - if (contents->n_entries > lines) { // draw position bar at the right - const u32 bar_height_min = 32; - const u32 bar_width = 2; - + if (contents->n_entries > lines) { // draw position bar at the right u32 bar_height = (lines * SCREEN_HEIGHT) / contents->n_entries; 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); @@ -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, 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); - } + } else DrawRectangleF(false, SCREEN_WIDTH_BOT - bar_width, 0, bar_width, SCREEN_HEIGHT, COLOR_STD_BG); } u32 GodMode() { @@ -217,10 +216,10 @@ u32 GodMode() { if (n_errors) ShowPrompt(false, "Failed deleting %u/%u path(s)", n_errors, n_marked); } } else { - char namestr[20+1]; - TruncateString(namestr, current_dir->entry[cursor].name, 20, 12); + char namestr[36+1]; + TruncateString(namestr, current_dir->entry[cursor].name, 36, 12); 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); if (cursor >= current_dir->n_entries) @@ -248,11 +247,11 @@ u32 GodMode() { if (ShowPrompt(true, promptstr)) { for (u32 c = 0; c < clipboard->n_entries; c++) { if (!PathCopy(current_path, clipboard->entry[c].path)) { - char namestr[20+1]; - TruncateString(namestr, clipboard->entry[c].name, 20, 12); + char namestr[36+1]; + TruncateString(namestr, clipboard->entry[c].name, 36, 12); if (c + 1 < clipboard->n_entries) { - if (!ShowPrompt(true, "Failed copying \"%s\"\nContinue?", namestr)) break; - } else ShowPrompt(false, "Failed copying \"%s\"\n", namestr); + if (!ShowPrompt(true, "Failed copying path:\n%s\nProcess remaining?", namestr)) break; + } else ShowPrompt(false, "Failed copying path:\n%s", namestr); } } }