From 7ab86c87a3acd5ee13e3e3c24084f64f83600798 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Wed, 2 Mar 2016 14:01:20 +0100 Subject: [PATCH] Misc bugfixes + non working copy / delete features --- source/draw.c | 17 +++++++---- source/fatfs/diskio.c | 2 +- source/fs.c | 28 ++++++++++-------- source/godmode.c | 66 +++++++++++++++++++++++++++++++++++-------- 4 files changed, 84 insertions(+), 29 deletions(-) diff --git a/source/draw.c b/source/draw.c index c233fb5..966c919 100644 --- a/source/draw.c +++ b/source/draw.c @@ -118,12 +118,13 @@ u32 GetDrawStringHeight(const char* str) { u32 GetDrawStringWidth(char* str) { u32 width = 0; char* old_lf = str; - for (char* lf = strchr(str, '\n'); (lf != NULL); lf = strchr(lf + 1, '\n')) { + char* str_end = str + strnlen(str, 512); + for (char* lf = strchr(str, '\n'); lf != NULL; lf = strchr(lf + 1, '\n')) { if ((lf - old_lf) > width) width = lf - old_lf; old_lf = lf; } - if (old_lf == str) - width = strnlen(str, 256); + if (str_end - old_lf > width) + width = str_end - old_lf; width *= 8; return width; } @@ -170,6 +171,7 @@ bool ShowPrompt(bool ask, const char *format, ...) { u32 str_width, str_height; u32 x, y; + bool ret = true; char str[512] = {}; // 512 should be more than enough va_list va; @@ -180,6 +182,7 @@ bool ShowPrompt(bool ask, const char *format, ...) str_width = GetDrawStringWidth(str); str_height = GetDrawStringHeight(str) + (2 * 10); + if (str_width < 18*8) str_width = 18 * 8; x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; @@ -190,12 +193,15 @@ bool ShowPrompt(bool ask, const char *format, ...) while (true) { u32 pad_state = InputWait(); if (pad_state & BUTTON_A) break; - else if (ask && (pad_state & BUTTON_B)) return false; + else if (ask && (pad_state & BUTTON_B)) { + ret = false; + break; + } } ClearScreenF(true, false, COLOR_STD_BG); - return true; + return ret; } bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { @@ -227,6 +233,7 @@ bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { str_width = GetDrawStringWidth(str); str_height = GetDrawStringHeight(str) + (3*10); + if (str_width < 24) str_width = 24; x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - (str_height)) / 2; diff --git a/source/fatfs/diskio.c b/source/fatfs/diskio.c index 51725f1..166b172 100644 --- a/source/fatfs/diskio.c +++ b/source/fatfs/diskio.c @@ -159,7 +159,7 @@ DRESULT disk_read ( UINT count /* Number of sectors to read */ ) { - if ((pdrv > 0) && mode_n3ds) // is this really set at this point? + if ((pdrv > 0) && mode_n3ds) pdrv += 6; BYTE type = DriveInfo[pdrv].type; diff --git a/source/fs.c b/source/fs.c index e950156..e65885b 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 = 4 * 1024 * 1024; +static size_t main_buffer_size = 128 * 1024; // write permission level - careful with this static u32 write_permission_level = 1; @@ -46,7 +46,7 @@ void DeinitFS() { } bool CheckWritePermissions(const char* path) { - u32 pdrv = *path - '0'; + u32 pdrv = (*path) - '0'; if ((pdrv > 6) || (*(path+1) != ':')) { ShowPrompt(false, "Invalid path"); @@ -144,18 +144,18 @@ bool PathCopyWorker(char* dest, char* orig) { DIR pdir; char* fname = orig + strnlen(orig, 256); - *(fname++) = '/'; - fno.lfname = fname; - fno.lfsize = 256 - (fname - orig); - - if (f_stat(dest, NULL) != FR_OK) - f_mkdir(dest); - if (f_stat(dest, NULL) != FR_OK) + if ((f_stat(dest, NULL) != FR_OK) && (f_mkdir(dest) != FR_OK)) return false; if (f_opendir(&pdir, orig) != FR_OK) return false; + *(fname++) = '/'; + 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,6 +164,7 @@ bool PathCopyWorker(char* dest, char* orig) { ret = true; break; } else if (!PathCopyWorker(dest, orig)) { + ShowPrompt(false, "Failed:\n%s\n%s", orig, dest); break; } } @@ -185,6 +186,7 @@ bool PathCopyWorker(char* dest, char* orig) { f_lseek(&ofile, 0); f_sync(&ofile); + ret = true; for (size_t pos = 0; pos < fsize; pos += main_buffer_size) { UINT bytes_read = 0; UINT bytes_written = 0; @@ -196,6 +198,7 @@ bool PathCopyWorker(char* dest, char* orig) { break; } } + ShowProgress(1, 1, orig, false); f_close(&ofile); f_close(&dfile); @@ -219,16 +222,16 @@ bool PathDeleteWorker(char* fpath) { // the deletion process takes place here if (f_stat(fpath, &fno) != FR_OK) return false; // fpath does not exist - if (fno.fattrib & AM_DIR) { // processing folders... + if (fno.fattrib & AM_DIR) { // process folder contents DIR pdir; char* fname = fpath + strnlen(fpath, 256); + if (f_opendir(&pdir, fpath) != FR_OK) + return false; *(fname++) = '/'; fno.lfname = fname; fno.lfsize = 256 - (fname - fpath); - if (f_opendir(&pdir, fpath) != FR_OK) - return false; while (f_readdir(&pdir, &fno) == FR_OK) { if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0)) continue; // filter out virtual entries @@ -241,6 +244,7 @@ bool PathDeleteWorker(char* fpath) { } } f_closedir(&pdir); + *(--fname) = '\0'; } else { // processing files... ret = (f_unlink(fpath) == FR_OK); } diff --git a/source/godmode.c b/source/godmode.c index 3bb18e6..40a1b1e 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -69,14 +69,16 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c // bottom: inctruction block char instr[256]; - snprintf(instr, 256, "%s%s%s%s", + snprintf(instr, 256, "%s%s%s%s%s", "GodMode9 File Explorer v0.0.4\n", // generic start part - (*curr_path) ? "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - COPY file(s) / [+R] CREATE dir\n" : - (GetWritePermissions() <= 1) ? "X - Unlock EmuNAND writing\nY - Unlock SysNAND writing\n" : + (*curr_path) ? ((clipboard->n_entries == 0) ? "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - COPY file(s) / [+R] CREATE dir\n" : + "L - MARK files (use with \x18\x19\x1A\x1B)\nX - DELETE / [+R] RENAME file(s)\nY - PASTE file(s) / [+R] CREATE dir\n") : + ((GetWritePermissions() <= 1) ? "X - Unlock EmuNAND writing\nY - Unlock SysNAND writing\n" : (GetWritePermissions() == 2) ? "X - Relock EmuNAND writing\nY - Unlock SysNAND writing\n" : - "X - Relock EmuNAND writing\nY - Relock SysNAND writing\n", - (clipboard->n_entries) ? "SELECT - Clear Clipboard\n" : "", // only if clipboard is full - "R+L - Make a SCREENSHOT\nSTART - Reboot / [+\x1B] Poweroff"); // generic end part + "X - Relock EmuNAND writing\nY - Relock SysNAND writing\n"), + "R+L - Make a Screenshot\n", + (clipboard->n_entries) ? "SELECT - Clear Clipboard\n" : "SELECT - Restore Clipboard\n", // only if clipboard is full + "START - Reboot / [+\x1B] Poweroff"); // generic end part DrawStringF(true, (SCREEN_WIDTH_TOP - GetDrawStringWidth(instr)) / 2, SCREEN_HEIGHT - 4 - GetDrawStringHeight(instr), COLOR_STD_FONT, COLOR_STD_BG, instr); } @@ -135,6 +137,7 @@ u32 GodMode() { char current_path[256] = { 0x00 }; int mark_setting = -1; + u32 last_clipboard_size = 0; bool switched = false; u32 cursor = 0; @@ -143,7 +146,7 @@ u32 GodMode() { GetDirContents(current_dir, ""); clipboard->n_entries = 0; - while (true) { // this is the main loop + while (true) { // this is the main loop !!! EMPTY DIRS DrawUserInterface(current_path, &(current_dir->entry[cursor]), clipboard); DrawDirContents(current_dir, cursor); u32 pad_state = InputWait(); @@ -163,7 +166,7 @@ u32 GodMode() { else *current_path = '\0'; GetDirContents(current_dir, current_path); cursor = 0; - } else if ((pad_state & BUTTON_DOWN) && (cursor < current_dir->n_entries - 1)) { // cursor up + } else if ((pad_state & BUTTON_DOWN) && (cursor + 1 < current_dir->n_entries)) { // cursor up cursor++; } else if ((pad_state & BUTTON_UP) && cursor) { // cursor down cursor--; @@ -189,8 +192,8 @@ u32 GodMode() { current_dir->entry[cursor].marked ^= 0x1; mark_setting = current_dir->entry[cursor].marked; } - } else if ((pad_state & BUTTON_SELECT) && (clipboard->n_entries > 0)) { // clear clipboard - clipboard->n_entries = 0; + } else if (pad_state & BUTTON_SELECT) { // clear/restore clipboard + clipboard->n_entries = (clipboard->n_entries > 0) ? 0 : last_clipboard_size; } // highly specific commands @@ -202,7 +205,26 @@ u32 GodMode() { } } else if (!switched) { // standard unswitched command set if (pad_state & BUTTON_X) { // delete a file - // not implemented yet + u32 n_marked = 0; + for (u32 c = 0; c < current_dir->n_entries; c++) + if (current_dir->entry[c].marked) n_marked++; + if (n_marked) { + if (ShowPrompt(true, "Delete %u path(s)?", n_marked)) { + u32 n_errors = 0; + for (u32 c = 0; c < current_dir->n_entries; c++) + if (current_dir->entry[c].marked && !PathDelete(current_dir->entry[c].path)) + n_errors++; + 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); + if ((ShowPrompt(true, "Delete \"%s\"?", namestr)) && !PathDelete(current_dir->entry[cursor].path)) + ShowPrompt(false, "Failed deleting \"%s\"", namestr); + } + GetDirContents(current_dir, current_path); + if (cursor >= current_dir->n_entries) + cursor = current_dir->n_entries - 1; } else if ((pad_state & BUTTON_Y) && (clipboard->n_entries == 0)) { // fill clipboard for (u32 c = 0; c < current_dir->n_entries; c++) { if (current_dir->entry[c].marked) { @@ -215,6 +237,28 @@ u32 GodMode() { DirEntryCpy(&(clipboard->entry[0]), &(current_dir->entry[cursor])); clipboard->n_entries = 1; } + last_clipboard_size = clipboard->n_entries; + } else if (pad_state & BUTTON_Y) { // paste files + char promptstr[64]; + if (clipboard->n_entries == 1) { + char namestr[20+1]; + TruncateString(namestr, clipboard->entry[0].name, 20, 12); + snprintf(promptstr, 64, "Copy \"%s\" here?", namestr); + } else snprintf(promptstr, 64, "Copy %lu path(s) here?", clipboard->n_entries); + 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); + if (c + 1 < clipboard->n_entries) { + if (!ShowPrompt(true, "Failed copying \"%s\"\nContinue?", namestr)) break; + } else ShowPrompt(false, "Failed copying \"%s\"\n", namestr); + } + } + } + clipboard->n_entries = 0; + GetDirContents(current_dir, current_path); + ClearScreenF(true, false, COLOR_STD_BG); } } else { // switched command set // not implemented yet