From bf19767a824f0d1a162127bc084154402178afc9 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Tue, 1 Mar 2016 02:00:48 +0100 Subject: [PATCH] Enabled a write permission system Plus tons of design and under the hood changes --- source/draw.c | 79 ++++++++++++++++++++++++--- source/draw.h | 5 ++ source/fs.c | 36 +++++++++++- source/fs.h | 3 + source/godmode.c | 139 +++++++++++++++++++++++++++++++---------------- 5 files changed, 203 insertions(+), 59 deletions(-) diff --git a/source/draw.c b/source/draw.c index 34778c9..dd87f19 100644 --- a/source/draw.c +++ b/source/draw.c @@ -171,30 +171,92 @@ bool ShowPrompt(bool ask, const char *format, ...) u32 str_width, str_height; u32 x, y; - char str[384] = {}; // 384 should be more than enough + char str[512] = {}; // 512 should be more than enough va_list va; va_start(va, format); - vsnprintf(str, 384, format, va); + vsnprintf(str, 512, format, va); va_end(va); str_width = GetDrawStringWidth(str); str_height = GetDrawStringHeight(str) + (2 * 10); x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; - y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - str_height) / 2; + y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - (str_height+20)) / 2; ClearScreenF(true, false, COLOR_STD_BG); - DrawStringF(true, x, y, COLOR_STD_FONT, COLOR_STD_BG, (ask) ? "%s\n\n( to continue, to cancel)" : "%s\n\n( to continue)", str); + DrawStringF(true, x, y, COLOR_STD_FONT, COLOR_STD_BG, str); + DrawStringF(true, x, y + str_height, COLOR_STD_FONT, COLOR_STD_BG, (ask) ? "( yes, no)" : "( to continue)"); while (true) { u32 pad_state = InputWait(); if (pad_state & BUTTON_A) break; - else if (pad_state & BUTTON_B) return false; + else if (ask && (pad_state & BUTTON_B)) return false; } + ClearScreenF(true, false, COLOR_STD_BG); + return true; } +bool ShowUnlockSequence(u32 seqlvl, const char *format, ...) { + const u32 seqcolors[4] = { COLOR_STD_FONT, COLOR_GREEN, COLOR_YELLOW, COLOR_RED }; + const u32 sequences[4][5] = { + { BUTTON_RIGHT, BUTTON_DOWN, BUTTON_RIGHT, BUTTON_DOWN, BUTTON_A }, + { BUTTON_LEFT, BUTTON_DOWN, BUTTON_RIGHT, BUTTON_UP, BUTTON_A }, + { BUTTON_LEFT, BUTTON_RIGHT, BUTTON_DOWN, BUTTON_UP, BUTTON_A }, + { BUTTON_LEFT, BUTTON_UP, BUTTON_RIGHT, BUTTON_UP, BUTTON_A } + }; + const char seqsymbols[4][5] = { + { '\x1A', '\x19', '\x1A', '\x19', 'A' }, + { '\x1B', '\x19', '\x1A', '\x18', 'A' }, + { '\x1B', '\x1A', '\x19', '\x18', 'A' }, + { '\x1B', '\x18', '\x1A', '\x18', 'A' }, + }; + const u32 len = 5; + u32 lvl = 0; + + u32 str_width, str_height; + u32 x, y; + + char str[512] = {}; // 512 should be more than enough + va_list va; + + va_start(va, format); + vsnprintf(str, 512, format, va); + va_end(va); + + str_width = GetDrawStringWidth(str); + str_height = GetDrawStringHeight(str) + (2 * 10); + x = (str_width >= SCREEN_WIDTH_TOP) ? 0 : (SCREEN_WIDTH_TOP - str_width) / 2; + y = (str_height >= SCREEN_HEIGHT) ? 0 : (SCREEN_HEIGHT - (str_height + 30)) / 2; + + ClearScreenF(true, false, COLOR_STD_BG); + DrawStringF(true, x, y, COLOR_STD_FONT, COLOR_STD_BG, str); + DrawStringF(true, x, y + str_height, COLOR_STD_FONT, COLOR_STD_BG, "To proceed, enter this:"); + + while (true) { + for (u32 n = 0; n < len; n++) { + DrawStringF(true, x + (n*4*8), y + str_height + 10, + (lvl > n) ? seqcolors[seqlvl] : COLOR_GREY, COLOR_STD_BG, "<%c>", seqsymbols[seqlvl][n]); + } + if (lvl == len) + break; + u32 pad_state = InputWait(); + if (!(pad_state & BUTTON_ANY)) + continue; + else if (pad_state & sequences[seqlvl][lvl]) + lvl++; + else if (pad_state & BUTTON_B) + break; + else if (lvl == 0 || !(pad_state & sequences[seqlvl][lvl-1])) + lvl = 0; + } + + ClearScreenF(true, false, COLOR_STD_BG); + + return (lvl >= len); +} + void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen) { const u32 bar_width = 240; @@ -202,14 +264,15 @@ void ShowProgress(u64 current, u64 total, const char* opstr, bool clearscreen) 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); - u32 prog_width = ((total > 0) && (current <= total)) ? (current * (bar_width-2)) / total : 0; + 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); - DrawRectangleF(true, bar_pos_x + 1, bar_pos_y + 1, prog_width, bar_height - 2, 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); - DrawStringF(true, bar_pos_x, text_pos_y, COLOR_STD_FONT, COLOR_STD_BG, tempstr); + 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); } diff --git a/source/draw.h b/source/draw.h index 5506d80..184705e 100644 --- a/source/draw.h +++ b/source/draw.h @@ -23,6 +23,10 @@ #define COLOR_YELLOW RGB(0xFF, 0xFF, 0x00) #define COLOR_CYAN RGB(0xFF, 0x00, 0xFF) +#define COLOR_BRIGHTRED RGB(0xFF, 0x30, 0x30) +#define COLOR_BRIGHTYELLOW RGB(0xFF, 0xFF, 0x30) +#define COLOR_BRIGHTGREEN RGB(0x30, 0xFF, 0x30) + #define COLOR_TINTEDBLUE RGB(0x60, 0x60, 0x80) #define COLOR_TINTEDYELLOW RGB(0xD0, 0xD0, 0x60) #define COLOR_TINTEDGREEN RGB(0x70, 0x80, 0x70) @@ -65,4 +69,5 @@ void TruncateString(char* dest, const char* orig, int nsize, int tpos); 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); diff --git a/source/fs.c b/source/fs.c index b6381cb..e950156 100644 --- a/source/fs.c +++ b/source/fs.c @@ -54,13 +54,16 @@ bool CheckWritePermissions(const char* path) { } if ((pdrv >= 1) && (pdrv <= 3) && (write_permission_level < 3)) { - ShowPrompt(false, "Writing to the SysNAND is locked!\nUnlock it from the root menu."); + if (ShowPrompt(true, "Writing to the SysNAND is locked!\nUnlock it now?")) + return SetWritePermissions(3); return false; } else if ((pdrv >= 4) && (pdrv <= 6) && (write_permission_level < 2)) { - ShowPrompt(false, "Writing to the EmuNAND is locked!\nUnlock it from the root menu."); + if (ShowPrompt(true, "Writing to the EmuNAND is locked!\nUnlock it now?")) + return SetWritePermissions(2); return false; } else if ((pdrv == 0) && (write_permission_level < 1)) { - ShowPrompt(false, "Writing to the SD card is locked!\nUnlock it from the root menu."); + if (ShowPrompt(true, "Writing to the SD card is locked!\nUnlock it now?")) + return SetWritePermissions(1); return false; } @@ -68,11 +71,38 @@ bool CheckWritePermissions(const char* path) { } bool SetWritePermissions(u32 level) { + if (write_permission_level >= level) { + // no need to ask the user here + write_permission_level = level; + return true; + } + + switch (level) { + case 1: + if (!ShowUnlockSequence(1, "You want to enable SD card\nwriting permissions.")) + return false; + break; + case 2: + if (!ShowUnlockSequence(2, "You want to enable EmuNAND\nwriting permissions.\nThis is potentially dangerous!\nKeep a backup, just in case.")) + return false; + break; + case 3: + if (!ShowUnlockSequence(3, "!This is your only warning!\n \nYou want to enable SysNAND\nwriting permissions.\nThis is potentially dangerous\nand can brick your 3DS!\nHaving a SysNAND backup and\nNANDmod is recommended.")) + return false; + break; + default: + break; + } + write_permission_level = level; return true; } +u32 GetWritePermissions() { + return write_permission_level; +} + bool FileCreate(const char* path, u8* data, u32 size) { FIL file; UINT bytes_written = 0; diff --git a/source/fs.h b/source/fs.h index 9dd0f0a..ad3f4c1 100644 --- a/source/fs.h +++ b/source/fs.h @@ -32,6 +32,9 @@ bool CheckWritePermissions(const char* path); /** Set new write permissions */ bool SetWritePermissions(u32 level); +/** Get write permissions */ +u32 GetWritePermissions(); + /** Create / overwrite file and write the provided data to it **/ bool FileCreate(const char* path, u8* data, u32 size); diff --git a/source/godmode.c b/source/godmode.c index ede284f..1218c72 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -3,19 +3,32 @@ #include "hid.h" #include "fs.h" -#define COLOR_TOP_BAR COLOR_WHITE +#define COLOR_TOP_BAR ((GetWritePermissions() == 0) ? COLOR_WHITE : (GetWritePermissions() == 1) ? COLOR_BRIGHTGREEN : (GetWritePermissions() == 2) ? COLOR_BRIGHTYELLOW : COLOR_BRIGHTRED) #define COLOR_SIDE_BAR COLOR_DARKGREY #define COLOR_MARKED COLOR_TINTEDYELLOW #define COLOR_FILE COLOR_TINTEDGREEN #define COLOR_DIR COLOR_TINTEDBLUE #define COLOR_ROOT COLOR_GREY -void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* clipboard) { - const u32 info_start = 16; +void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* clipboard, bool switched) { + const u32 info_start = 18; + + static u32 state_prev = 0xFFFFFFFF; + u32 state_curr = + ((*curr_path) ? (1<<0) : 0) | + ((clipboard->n_entries) ? (1<<1) : 0) | + ((switched) ? (1<<2) : 0) | + (GetWritePermissions()<<3); + char bytestr0[32]; char bytestr1[32]; char tempstr[64]; + if (state_prev != state_curr) { + ClearScreenF(true, false, COLOR_STD_BG); + state_prev = state_curr; + } + // top bar - current path & free/total storage DrawRectangleF(true, 0, 0, SCREEN_WIDTH_TOP, 12, COLOR_TOP_BAR); if (strncmp(curr_path, "", 256) != 0) { @@ -52,11 +65,25 @@ void DrawUserInterface(const char* curr_path, DirEntry* curr_entry, DirStruct* c } *tempstr = '\0'; if (clipboard->n_entries > 10) snprintf(tempstr, 60, "+ %lu more", clipboard->n_entries - 10); - DrawStringF(true, SCREEN_WIDTH_TOP - (20*8) - 4, info_start + 12 + (10*10), COLOR_GREY, COLOR_STD_BG, "%20s", tempstr); + DrawStringF(true, SCREEN_WIDTH_TOP - (20*8) - 4, info_start + 12 + (10*10), COLOR_DARKGREY, COLOR_STD_BG, "%20s", tempstr); // bottom: inctruction block - char* instr = "GodMode 9 v0.0.3\n//<\x18\x19\x1A\x1B> - Navigation\n(+<\x18\x19\x1A\x1B> - Mark entries(s)\n - Make a Screenshot\n - Reboot/Poweroff"; + char instr[256]; + snprintf(instr, 256, "%s%s%s%s%s%s", + "GodMode 9 v0.0.4\n", // generic start part + (*curr_path && !switched) ? " (hold) - Switch commands\n (+<\x18\x19\x1A\x1B>) - Mark entries\n" : + (*curr_path && switched) ? " (rel.) - Switch commands\n - Make a Screenshot\n" : + " - Make a Screenshot\n", + (!(*curr_path)) ? "" : + (!switched) ? " - DELETE file(s)\n - ADD file(s) to clipboard\n" : + " - RENAME file\n - CREATE directory\n", + (*curr_path) ? "" : + (GetWritePermissions() <= 1) ? " - Unlock EmuNAND writing\n - Unlock SysNAND writing\n" : + (GetWritePermissions() == 2) ? " - Relock EmuNAND writing\n - Unlock SysNAND writing\n" : + " - Relock EmuNAND writing\n - Relock SysNAND writing\n", + (clipboard->n_entries) ? "