From 36ad88176c510a7aec73d59f9768705e75fe80d2 Mon Sep 17 00:00:00 2001 From: robshape Date: Thu, 20 Apr 2023 21:08:53 +0200 Subject: [PATCH] feat: Add to Favorites folder (Part 1) --- README.md | 2 +- makefile | 1 + src/common/defines.h | 4 +- src/minui/minui.c | 125 +++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 127 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 5ae046f..9a138ef 100644 --- a/README.md +++ b/README.md @@ -112,7 +112,7 @@ Run `./start-toolchain.sh` and then `make all` in the Docker container shell. - ~~Include extras in release by default~~ - ~~Add Clear Recent setting~~ - ~~Refactor Tools to Settings~~ -- Add "mark as finished" OR "add as favorite" to menu +- Add to Favorites - Improve battery capacity readings (2100 mAh, 2600 mAh, 3500 mAh) - Adjust overclocking - Update Installation instructions for microSD cards of all sizes diff --git a/makefile b/makefile index 6a3cccd..339b311 100644 --- a/makefile +++ b/makefile @@ -118,6 +118,7 @@ report: clean: rm -rf ./build + rm -rf ./releases cd ./src/libmsettings && make clean cd ./src/keymon && make clean cd ./src/minui && make clean diff --git a/src/common/defines.h b/src/common/defines.h index 072adc1..5565f96 100644 --- a/src/common/defines.h +++ b/src/common/defines.h @@ -56,6 +56,8 @@ #define PAKS_PATH SYSTEM_PATH "/paks" #define RECENT_PATH USERDATA_PATH "/.minui/recent.txt" #define FAUX_RECENT_PATH SDCARD_PATH "/Recently Played" +#define FAVORITE_PATH USERDATA_PATH "/.minui/favorite.txt" +#define FAUX_FAVORITE_PATH SDCARD_PATH "/Favorites" #define COLLECTIONS_PATH SDCARD_PATH "/Collections" #define LAST_PATH "/tmp/last.txt" // transient @@ -121,4 +123,4 @@ #define SCALE4(a,b,c,d) ((a)*SCREEN_SCALE),((b)*SCREEN_SCALE),((c)*SCREEN_SCALE),((d)*SCREEN_SCALE) -#endif \ No newline at end of file +#endif diff --git a/src/minui/minui.c b/src/minui/minui.c index 2ed13e1..f30859a 100644 --- a/src/minui/minui.c +++ b/src/minui/minui.c @@ -215,7 +215,7 @@ static void getUniqueName(Entry* entry, char* out_name) { } static void Directory_index(Directory* self) { - int skip_index = exactMatch(FAUX_RECENT_PATH, self->path) || prefixMatch(COLLECTIONS_PATH, self->path); // not alphabetized + int skip_index = exactMatch(FAUX_RECENT_PATH, self->path) || exactMatch(FAUX_FAVORITE_PATH, self->path) || prefixMatch(COLLECTIONS_PATH, self->path); // not alphabetized Entry* prior = NULL; int alpha = -1; @@ -259,6 +259,7 @@ static void Directory_index(Directory* self) { static Array* getRoot(void); static Array* getRecents(void); +static Array* getFavorites(void); static Array* getCollection(char* path); static Array* getDiscs(char* path); static Array* getEntries(char* path); @@ -276,6 +277,9 @@ static Directory* Directory_new(char* path, int selected) { else if (exactMatch(path, FAUX_RECENT_PATH)) { self->entries = getRecents(); } + else if (exactMatch(path, FAUX_FAVORITE_PATH)) { + self->entries = getFavorites(); + } else if (!exactMatch(path, COLLECTIONS_PATH) && prefixMatch(COLLECTIONS_PATH, path)) { self->entries = getCollection(path); } @@ -349,9 +353,48 @@ static void RecentArray_free(Array* self) { /////////////////////////////////////// +typedef struct Favorite { + char* path; // NOTE: this is without the SDCARD_PATH prefix! + int available; +} Favorite; +static Favorite* Favorite_new(char* path) { + Favorite* self = malloc(sizeof(Favorite)); + + char sd_path[256]; // only need to get emu name + sprintf(sd_path, "%s%s", SDCARD_PATH, path); + + char emu_name[256]; + getEmuName(sd_path, emu_name); + + self->path = strdup(path); + self->available = hasEmu(emu_name); + return self; +} +static void Favorite_free(Favorite* self) { + free(self->path); + free(self); +} + +static int FavoriteArray_indexOf(Array* self, char* str) { + for (int i=0; icount; i++) { + Favorite* item = self->items[i]; + if (exactMatch(item->path, str)) return i; + } + return -1; +} +static void FavoriteArray_free(Array* self) { + for (int i=0; icount; i++) { + Favorite_free(self->items[i]); + } + Array_free(self); +} + +/////////////////////////////////////// + static Directory* top; static Array* stack; // DirectoryArray static Array* recents; // RecentArray +static Array* favorites; // FavoriteArray static int quit = 0; static int can_resume = 0; @@ -397,6 +440,29 @@ static void addRecent(char* path) { saveRecents(); } +static void saveFavorites(void) { + FILE* file = fopen(FAVORITE_PATH, "w"); + if (file) { + for (int i=0; icount; i++) { + Favorite* favorite = favorites->items[i]; + fputs(favorite->path, file); + putc('\n', file); + } + fclose(file); + } +} +static void toggleFavorite(char* path) { + path += strlen(SDCARD_PATH); // makes paths platform agnostic + int id = FavoriteArray_indexOf(favorites, path); + if (id==-1) { // add + Array_unshift(favorites, Favorite_new(path)); + } + else if (id>0) { // remove + // TODO: remove from favorite + } + saveFavorites(); +} + static int hasEmu(char* emu_name) { char pak_path[256]; sprintf(pak_path, "%s/Emus/%s.pak/launch.sh", PAKS_PATH, emu_name); @@ -506,7 +572,35 @@ static int hasRecents(void) { saveRecents(); StringArray_free(parent_paths); - return has>0; + //return has>0; + return 1; // Always show directory, even if empty. +} +static int hasFavorites(void) { + int has = 0; + + FILE* file = fopen(FAVORITE_PATH, "r"); // newest at top + if (file) { + char line[256]; + while (fgets(line,256,file)!=NULL) { + normalizeNewline(line); + trimTrailingNewlines(line); + if (strlen(line)==0) continue; // skip empty lines + + char sd_path[256]; + sprintf(sd_path, "%s%s", SDCARD_PATH, line); + if (exists(sd_path)) { + Favorite* favorite = Favorite_new(line); + if (favorite->available) has += 1; + Array_push(favorites, favorite); + } + } + fclose(file); + } + + saveFavorites(); + + //return has>0; + return 1; // Always show directory, even if empty. } static int hasCollections(void) { int has = 0; @@ -551,6 +645,7 @@ static Array* getRoot(void) { Array* root = Array_new(); if (hasRecents()) Array_push(root, Entry_new(FAUX_RECENT_PATH, ENTRY_DIR)); + if (hasFavorites()) Array_push(root, Entry_new(FAUX_FAVORITE_PATH, ENTRY_DIR)); DIR *dh; @@ -637,6 +732,19 @@ static Array* getRecents(void) { } return entries; } +static Array* getFavorites(void) { + Array* entries = Array_new(); + for (int i=0; icount; i++) { + Favorite* favorite = favorites->items[i]; + if (!favorite->available) continue; + + char sd_path[256]; + sprintf(sd_path, "%s%s", SDCARD_PATH, favorite->path); + int type = suffixMatch(".pak", sd_path) ? ENTRY_PAK : ENTRY_ROM; // ??? + Array_push(entries, Entry_new(sd_path, type)); + } + return entries; +} static Array* getCollection(char* path) { Array* entries = Array_new(); FILE* file = fopen(path, "r"); @@ -1075,6 +1183,8 @@ static void saveLast(char* path) { // your most recently played game will always be at // the top which is also the default selection path = FAUX_RECENT_PATH; + } else if (exactMatch(top->path, FAUX_FAVORITE_PATH)) { + path = FAUX_FAVORITE_PATH; } putFile(LAST_PATH, path); } @@ -1145,12 +1255,14 @@ static void loadLast(void) { // call after loading root directory static void Menu_init(void) { stack = Array_new(); // array of open Directories recents = Array_new(); + favorites = Array_new(); openDirectory(SDCARD_PATH, 0); loadLast(); // restore state when available } static void Menu_quit(void) { RecentArray_free(recents); + FavoriteArray_free(favorites); DirectoryArray_free(stack); } @@ -1316,6 +1428,13 @@ int main (int argc, char *argv[]) { // can_resume = 0; if (total>0) readyResume(top->entries->items[top->selected]); } + else if (total>0 && PAD_justPressed(BTN_SELECT)) { + Entry* entry = top->entries->items[top->selected]; + if (entry->type == ENTRY_ROM) { + toggleFavorite(entry->path); + dirty = 1; + } + } } POW_update(&dirty, &show_setting, NULL, NULL); @@ -1497,4 +1616,4 @@ int main (int argc, char *argv[]) { POW_quit(); GFX_quit(); QuitSettings(); -} \ No newline at end of file +}