diff --git a/README.md b/README.md index b5c95c9..db3f572 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,5 @@ Video: https://www.youtube.com/watch?v=eb-QpeHQWWY Download: https://www.dropbox.com/s/ovfbpkrjq5anq25/FBI.cia?dl=0 Requires [devkitARM](http://sourceforge.net/projects/devkitpro/files/devkitARM/) to build. + +Currently only compiles against a fork of ctrulib that adds two required functions. diff --git a/source/common.c b/source/common.c index 3516caf..a222eb5 100644 --- a/source/common.c +++ b/source/common.c @@ -645,6 +645,18 @@ bool app_launch(MediaType mediaType, App app) { return NS_RebootToTitle(mediaType, app.titleId) == 0; } +u64 fs_get_free_space(MediaType mediaType) { + u32 clusterSize; + u32 freeClusters; + if(mediaType == NAND) { + FSUSER_GetNandArchiveResource(NULL, NULL, &clusterSize, NULL, &freeClusters); + } else { + FSUSER_GetSdmcArchiveResource(NULL, NULL, &clusterSize, NULL, &freeClusters); + } + + return clusterSize * freeClusters; +} + void platform_init() { srvInit(); aptInit(); diff --git a/source/common.h b/source/common.h index 1c46515..e25c0df 100644 --- a/source/common.h +++ b/source/common.h @@ -111,6 +111,8 @@ bool app_install(MediaType mediaType, const char* path, bool (*onProgress)(int p bool app_delete(MediaType mediaType, App app); bool app_launch(MediaType mediaType, App app); +u64 fs_get_free_space(MediaType mediaType); + void platform_init(); void platform_cleanup(); bool platform_is_running(); diff --git a/source/ui.cpp b/source/ui.cpp index f0a4fe5..71b499b 100644 --- a/source/ui.cpp +++ b/source/ui.cpp @@ -80,13 +80,16 @@ void uiFreeVectorContents(std::vector* contents) { } } -UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaType destination, Mode mode) { +UIResult uiDisplaySelector(char** selected, std::vector* contents, const char* currDir, MediaType destination, Mode mode) { const char* selectCia = mode == INSTALL ? "Select a CIA to install." : "Select a CIA to delete."; const char* pressL = "Press L to switch destinations."; const char* pressR = "Press R to switch between installing and deleting."; const char* destString = destination == NAND ? "Destination: NAND" : "Destination: SD"; const char* modeString = mode == INSTALL ? "Mode: Install" : "Mode: Delete"; + char* freeSpace = sdprintf("Free space: %llu bytes", fs_get_free_space(destination)); + char* requiredSpace = NULL; + unsigned int cursor = 0; unsigned int scroll = 0; int horizScroll = 0; @@ -115,6 +118,7 @@ UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaT break; } + bool cursorChanged = false; if(input_is_pressed(BUTTON_DOWN) && cursor < contents->size() - 1) { cursor++; int diff = cursor - scroll; @@ -124,6 +128,7 @@ UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaT horizScroll = 0; horizEndTime = 0; + cursorChanged = true; } if(input_is_pressed(BUTTON_UP) && cursor > 0) { @@ -135,6 +140,22 @@ UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaT horizScroll = 0; horizEndTime = 0; + cursorChanged = true; + } + + if(cursorChanged && currDir != NULL) { + char* currSelection = contents->at(cursor); + char* path = sdprintf("%s/%s", currDir, currSelection); + if(strcmp(currSelection, ".") != 0 && strcmp(currSelection, "..") != 0 && !uiIsDirectory(path)) { + struct stat st; + stat(path, &st); + requiredSpace = sdprintf("Required space: %lu bytes", st.st_size); + } else if(requiredSpace != NULL) { + free(requiredSpace); + requiredSpace = NULL; + } + + free(path); } screen_begin_draw(); @@ -179,7 +200,11 @@ UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaT screen_draw_string(selectCia, (screen_get_width() - screen_get_str_width(selectCia)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2 - screen_get_str_height(selectCia), 255, 255, 255); screen_draw_string(pressL, (screen_get_width() - screen_get_str_width(pressL)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2, 255, 255, 255); - screen_draw_string(pressR, (screen_get_width() - screen_get_str_width(pressR)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2 + screen_get_str_height(pressR), 255, 255, 255); + screen_draw_string(pressR, (screen_get_width() - screen_get_str_width(pressR)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2 + screen_get_str_height(pressL), 255, 255, 255); + screen_draw_string(freeSpace, (screen_get_width() - screen_get_str_width(freeSpace)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2 + screen_get_str_height(pressL) * 4, 255, 255, 255); + if(requiredSpace != NULL) { + screen_draw_string(requiredSpace, (screen_get_width() - screen_get_str_width(requiredSpace)) / 2, (screen_get_height() - screen_get_str_height(pressL)) / 2 + screen_get_str_height(pressL) * 5, 255, 255, 255); + } screen_draw_string(destString, 0, screen_get_height() - screen_get_str_height(destString), 255, 255, 255); screen_draw_string(modeString, screen_get_width() - screen_get_str_width(modeString), screen_get_height() - screen_get_str_height(modeString), 255, 255, 255); @@ -188,6 +213,11 @@ UIResult uiDisplaySelector(char** selected, std::vector* contents, MediaT screen_swap_buffers(); } + free(freeSpace); + if(requiredSpace != NULL) { + free(requiredSpace); + } + if(!platform_is_running()) { result = EXIT_APP; } @@ -200,7 +230,7 @@ UIResult uiSelectFile(char** selected, const char* directory, const char* extens UIResult result; while(true) { char* selectedEntry = NULL; - UIResult res = uiDisplaySelector(&selectedEntry, contents, *destination, *mode); + UIResult res = uiDisplaySelector(&selectedEntry, contents, directory, *destination, *mode); if(res == SWITCH_DEST) { if(*destination == NAND) { *destination = SD; @@ -225,8 +255,7 @@ UIResult uiSelectFile(char** selected, const char* directory, const char* extens continue; } - char* path = (char*) malloc(strlen(directory) + strlen(selectedEntry) + 2); - snprintf(path, strlen(directory) + strlen(selectedEntry) + 2, "%s/%s", directory, selectedEntry); + char* path = sdprintf("%s/%s", directory, selectedEntry); if(uiIsDirectory(path)) { char *select; UIResult dirRes = uiSelectFile(&select, path, extension, destination, mode); @@ -257,7 +286,7 @@ UIResult uiSelectTitle(App* selected, MediaType* destination, Mode* mode) { UIResult result; while(true) { char* selectedEntry = NULL; - UIResult res = uiDisplaySelector(&selectedEntry, contents, *destination, *mode); + UIResult res = uiDisplaySelector(&selectedEntry, contents, NULL, *destination, *mode); if(selectedEntry != NULL && strcmp(selectedEntry, "None") == 0) { continue; }