diff --git a/Makefile b/Makefile index 4f76af054..f0e3f0b9f 100644 --- a/Makefile +++ b/Makefile @@ -73,7 +73,7 @@ endif FRONTEND_OBJS = pad.o xparam.o fntsys.o renderman.o menusys.o OSDHistory.o system.o lang.o lang_internal.o config.o hdd.o dialogs.o \ dia.o ioman.o texcache.o themes.o supportbase.o bdmsupport.o ethsupport.o hddsupport.o zso.o lz4.o \ - appsupport.o gui.o guigame.o textures.o opl.o atlas.o nbns.o httpclient.o gsm.o cheatman.o sound.o ps2cnf.o + appsupport.o favsupport.o gui.o guigame.o textures.o opl.o atlas.o nbns.o httpclient.o gsm.o cheatman.o sound.o ps2cnf.o IOP_OBJS = iomanx.o filexio.o ps2fs.o usbd.o bdmevent.o \ bdm.o bdmfs_fatfs.o usbmass_bd.o iLinkman.o IEEE1394_bd.o mx4sio_bd.o \ @@ -92,14 +92,14 @@ EECORE_OBJS = ee_core.o ioprp.o util.o \ ingame_smstcpip.o smap_ingame.o smbman.o smbinit.o PNG_ASSETS = load0 load1 load2 load3 load4 load5 load6 load7 usb usb_bd ilk_bd \ - m4s_bd hdd_bd hdd eth app cross triangle circle square select start left right \ + m4s_bd hdd_bd hdd eth app fav fav_mark cross triangle circle square select start left right \ background info cover disc screen ELF HDL ISO ZSO UL APPS CD DVD Aspect_s Aspect_w Aspect_w1 \ Aspect_w2 Device_1 Device_2 Device_3 Device_4 Device_5 Device_6 Device_all Rating_0 \ Rating_1 Rating_2 Rating_3 Rating_4 Rating_5 Scan_240p Scan_240p1 Scan_480i Scan_480p \ Scan_480p1 Scan_480p2 Scan_480p3 Scan_480p4 Scan_480p5 Scan_576i Scan_576p Scan_720p \ Scan_1080i Scan_1080i2 Scan_1080p Vmode_multi Vmode_ntsc Vmode_pal logo case apps_case\ - Index_0 Index_1 Index_2 Index_3 Index_4 - # unused icons - up down l1 l2 l3 r1 r2 r3 + Index_0 Index_1 Index_2 Index_3 Index_4 R3 + # unused icons - up down l1 l2 l3 r1 r2 GFX_OBJS = $(PNG_ASSETS:%=%_png.o) poeveticanew.o icon_sys.o icon_icn.o diff --git a/gfx/app.png b/gfx/app.png index d29c7d1d2..d5ef36894 100644 Binary files a/gfx/app.png and b/gfx/app.png differ diff --git a/gfx/eth.png b/gfx/eth.png index 355b84a64..150b029f9 100644 Binary files a/gfx/eth.png and b/gfx/eth.png differ diff --git a/gfx/fav.png b/gfx/fav.png new file mode 100644 index 000000000..4be87b16a Binary files /dev/null and b/gfx/fav.png differ diff --git a/gfx/fav_mark.png b/gfx/fav_mark.png new file mode 100644 index 000000000..68907528f Binary files /dev/null and b/gfx/fav_mark.png differ diff --git a/gfx/hdd.png b/gfx/hdd.png index c14f70fe6..470e312a2 100644 Binary files a/gfx/hdd.png and b/gfx/hdd.png differ diff --git a/gfx/hdd_bd.png b/gfx/hdd_bd.png index 6bb661856..d9f60d20c 100644 Binary files a/gfx/hdd_bd.png and b/gfx/hdd_bd.png differ diff --git a/gfx/ilk_bd.png b/gfx/ilk_bd.png index b67e50c59..8d6538886 100644 Binary files a/gfx/ilk_bd.png and b/gfx/ilk_bd.png differ diff --git a/gfx/m4s_bd.png b/gfx/m4s_bd.png index f6bb6a0ac..b05394ef4 100644 Binary files a/gfx/m4s_bd.png and b/gfx/m4s_bd.png differ diff --git a/gfx/udp_bd.png b/gfx/udp_bd.png index 0fe575a7d..c8df1e0f0 100644 Binary files a/gfx/udp_bd.png and b/gfx/udp_bd.png differ diff --git a/gfx/usb.png b/gfx/usb.png index fdab40dc4..fd2cf3e1d 100644 Binary files a/gfx/usb.png and b/gfx/usb.png differ diff --git a/gfx/usb_bd.png b/gfx/usb_bd.png index 0c47d7d96..1926cec7e 100644 Binary files a/gfx/usb_bd.png and b/gfx/usb_bd.png differ diff --git a/include/config.h b/include/config.h index c16144207..87147b32a 100644 --- a/include/config.h +++ b/include/config.h @@ -94,6 +94,7 @@ enum CONFIG_INDEX { #define CONFIG_OPL_HDD_MODE "hdd_mode" #define CONFIG_OPL_ETH_MODE "eth_mode" #define CONFIG_OPL_APP_MODE "app_mode" +#define CONFIG_OPL_FAV_MODE "fav_mode" #define CONFIG_OPL_BDM_CACHE "bdm_cache" #define CONFIG_OPL_HDD_CACHE "hdd_cache" #define CONFIG_OPL_SMB_CACHE "smb_cache" diff --git a/include/dialogs.h b/include/dialogs.h index f163befde..8afb330f3 100644 --- a/include/dialogs.h +++ b/include/dialogs.h @@ -34,6 +34,7 @@ enum UI_ITEMS { CFG_HDDMODE, CFG_ETHMODE, CFG_APPMODE, + CFG_FAVMODE, CFG_BDMCACHE, CFG_HDDCACHE, CFG_SMBCACHE, diff --git a/include/favsupport.h b/include/favsupport.h new file mode 100644 index 000000000..b22ec4a89 --- /dev/null +++ b/include/favsupport.h @@ -0,0 +1,16 @@ +#ifndef __FAV_SUPPORT_H +#define __FAV_SUPPORT_H + +#include "include/iosupport.h" + +#define FAV_MODE_UPDATE_DELAY 240 + +item_list_t *favGetObject(int initOnly); +unsigned char favGetFlags(item_list_t *itemList); + +void writeFavouritesFile(submenu_item_t *items, int size); +submenu_item_t *readFavouritesFile(int *out_size); +void addFavouriteItem(const submenu_item_t *item); +void removeFavouriteByIdAndText(int id, const char *text); + +#endif diff --git a/include/gui.h b/include/gui.h index 44c697409..778837961 100644 --- a/include/gui.h +++ b/include/gui.h @@ -38,6 +38,7 @@ struct gui_update_t int id; int text_id; int selected; + void *owner; } submenu; struct diff --git a/include/iosupport.h b/include/iosupport.h index e8c905a73..d46eeb488 100644 --- a/include/iosupport.h +++ b/include/iosupport.h @@ -15,6 +15,7 @@ enum IO_MODES { ETH_MODE, HDD_MODE, APP_MODE, + FAV_MODE, MODE_COUNT }; diff --git a/include/menusys.h b/include/menusys.h index 0cbf9bf9f..b71564800 100644 --- a/include/menusys.h +++ b/include/menusys.h @@ -21,6 +21,11 @@ typedef struct submenu_item int *cache_id; int *cache_uid; + + /// item_list_t that owns the submenu_item (for favourites) + void *owner; + + int favourited; } submenu_item_t; typedef struct submenu_list @@ -70,6 +75,8 @@ typedef struct menu_item void (*execSquare)(struct menu_item *curMenu); + void (*fav)(struct menu_item *curMenu); + /// hint list struct menu_hint_item *hints; } menu_item_t; @@ -90,7 +97,8 @@ void menuInitAppMenu(void); void menuAppendItem(menu_item_t *item); void submenuRebuildCache(submenu_list_t *submenu); -submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *text, int id, int text_id); +submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *text, int id, int text_id, void *owner); +submenu_list_t *submenuFindItemByIdAndText(submenu_list_t *submenu, int id, const char *text); void submenuRemoveItem(submenu_list_t **submenu, int id); void submenuDestroy(submenu_list_t **submenu); void submenuSort(submenu_list_t **submenu); diff --git a/include/opl.h b/include/opl.h index 2e06a4325..caeb173ee 100644 --- a/include/opl.h +++ b/include/opl.h @@ -119,6 +119,7 @@ extern int gBDMStartMode; extern int gHDDStartMode; extern int gETHStartMode; extern int gAPPStartMode; +extern int gFAVStartMode; extern int bdmCacheSize; extern int hddCacheSize; extern int smbCacheSize; @@ -218,6 +219,9 @@ void initSupport(item_list_t *itemList, int mode, int force_reinit); void setDefaultColors(void); +item_list_t *getFavouritesOwnerPointer(short int mode); +void loadFavourites(void); + #define MENU_ITEM_HEIGHT 19 #include "include/menusys.h" diff --git a/include/textures.h b/include/textures.h index 9407f43d6..270715565 100644 --- a/include/textures.h +++ b/include/textures.h @@ -18,11 +18,14 @@ enum INTERNAL_TEXTURE { HDD_ICON, ETH_ICON, APP_ICON, + FAV_ICON, + FAV_MARK, INDEX_0, INDEX_1, INDEX_2, INDEX_3, INDEX_4, + R3_ICON, LEFT_ICON, RIGHT_ICON, CROSS_ICON, @@ -38,8 +41,7 @@ enum INTERNAL_TEXTURE { L2_ICON, L3_ICON, R1_ICON, - R2_ICON, - R3_ICON, */ + R2_ICON, */ MAIN_BG, INFO_BG, COVER_DEFAULT, diff --git a/lng_tmpl/_base.yml b/lng_tmpl/_base.yml index c1edbcd19..067301bb4 100644 --- a/lng_tmpl/_base.yml +++ b/lng_tmpl/_base.yml @@ -70,7 +70,7 @@ gui_strings: - label: NET_GAMES string: ETH Games - label: APPS - string: Apps + string: Applications - label: THEME string: Theme - label: LANGUAGE @@ -692,3 +692,11 @@ gui_strings: string: 'Files found: %i' - label: CHEAT_SELECTION string: Cheat Selection +- label: FAV + string: Favourites +- label: FAVMODE + string: Favourites Start Mode +- label: FAV_HINT + string: Favourite +- label: FAV_MSG + string: "%s not allowed through Favourites Menu." diff --git a/src/dia.c b/src/dia.c index 36cc84440..1aef7f84b 100644 --- a/src/dia.c +++ b/src/dia.c @@ -563,6 +563,9 @@ static void diaRenderItem(int x, int y, struct UIItem *item, int selected, int h } } +static int maxScrollOffset = 0; +static int scrollOffset = 0; + /// renders whole ui screen (for given dialog setup) void diaRenderUI(struct UIItem *ui, short inMenu, struct UIItem *cur, int haveFocus) { @@ -573,7 +576,8 @@ void diaRenderUI(struct UIItem *ui, short inMenu, struct UIItem *cur, int haveFo // render all items struct UIItem *rc = ui; - int x = x0, y = y0, hmax = 0; + int x = x0, hmax = 0; + int y = y0 - scrollOffset; // adjust y position based on scroll offset while (rc->type != UI_TERMINATOR) { int w = 0, h = 0; @@ -877,6 +881,18 @@ int diaExecuteDialog(struct UIItem *ui, int uiId, short inMenu, int (*updater)(i setButtonDelay(KEY_UP, DIA_SCROLL_SPEED); setButtonDelay(KEY_DOWN, DIA_SCROLL_SPEED); + // calculate content height and maximum scroll offset + scrollOffset = 0; + int lineCount = 0; + struct UIItem *item = ui; + while (item && item->type != UI_TERMINATOR) { + if ((item->type == UI_BREAK) || (item->type == UI_SPLITTER)) + lineCount++; + item++; + } + int contentHeight = lineCount * 25; + maxScrollOffset = (contentHeight > screenHeight) ? (contentHeight - screenHeight) : 0; + // okay, we have the first selectable item // we can proceed with rendering etc. etc. while (1) { @@ -911,15 +927,21 @@ int diaExecuteDialog(struct UIItem *ui, int uiId, short inMenu, int (*updater)(i } if (getKey(KEY_UP)) { + scrollOffset = max(0, scrollOffset - 12); // prevent negative scroll offset newf = diaGetPrevLine(cur, ui); - if (newf == cur) + if (newf == cur) { newf = diaGetLastControl(ui); + scrollOffset = maxScrollOffset; + } } if (getKey(KEY_DOWN)) { + scrollOffset = min(maxScrollOffset, scrollOffset + 12); // prevent exceeding max scroll offset newf = diaGetNextLine(cur, ui); - if (newf == cur) + if (newf == cur) { newf = diaGetFirstControl(ui); + scrollOffset = 0; + } } if (newf != cur) { diff --git a/src/dialogs.c b/src/dialogs.c index d465d9dfb..388b33e2f 100644 --- a/src/dialogs.c +++ b/src/dialogs.c @@ -238,6 +238,11 @@ struct UIItem diaConfig[] = { {UI_ENUM, CFG_APPMODE, 1, 1, -1, 0, 0, {.intvalue = {0, 0}}}, {UI_BREAK}, + {UI_LABEL, 0, 1, 1, -1, -40, 0, {.label = {NULL, _STR_FAVMODE}}}, + {UI_SPACER}, + {UI_ENUM, CFG_FAVMODE, 1, 1, -1, 0, 0, {.intvalue = {0, 0}}}, + {UI_BREAK}, + {UI_LABEL, 0, 1, 1, -1, -40, 0, {.label = {NULL, _STR_DEFDEVICE}}}, {UI_SPACER}, {UI_ENUM, CFG_DEFDEVICE, 1, 1, -1, 0, 0, {.intvalue = {0, 0}}}, diff --git a/src/favsupport.c b/src/favsupport.c new file mode 100644 index 000000000..d039db8b5 --- /dev/null +++ b/src/favsupport.c @@ -0,0 +1,344 @@ +/* + Copyright 2024 + Licenced under Academic Free License version 3.0 + Review OpenPS2Loader README & LICENSE files for further details. + */ + +#include "include/opl.h" +#include "include/ioman.h" +#include "include/gui.h" +#include "include/lang.h" +#include "include/themes.h" +#include "include/favsupport.h" + +static int favItemCount = 0; + +static item_list_t favItemList; + +void favInit(item_list_t *itemList) +{ + LOG("FAVSUPPORT Init\n"); + configGetInt(configGetByType(CONFIG_OPL), "fav_frames_delay", &favItemList.delay); + favItemList.enabled = 1; +} + +item_list_t *favGetObject(int initOnly) +{ + if (initOnly && !favItemList.enabled) + return NULL; + return &favItemList; +} + +static int favNeedsUpdate(item_list_t *itemList) +{ + char filename[256]; + FILE *file; + int fileSize = 0; + + snprintf(filename, sizeof(filename), "%sfavourites.bin", configGetDir()); + + file = fopen(filename, "rb"); + if (file == NULL) + return 1; + + fseek(file, 0, SEEK_END); + fileSize = ftell(file); + fclose(file); + + int currentSize = favItemCount * sizeof(submenu_item_t); + + return fileSize != currentSize ? 1 : 0; +} + +static int favUpdateItemList(item_list_t *itemList) +{ + // Update list with updateFavouritesMenu() rather than updateMenuFromGameList() as id is randomly assigned based on i in count + // we need to keep the id of the owner to use its corresponding functions + // return a count of 0 so updateMenuFromGameList() doesn't attempt to update the list, we've done it already with loadFavourites() + + loadFavourites(); + return 0; +} + +static int favGetItemCount(item_list_t *itemList) +{ + // don't update cfgs for favourites menu items + + return 0; +} + +static char *favGetItemName(item_list_t *itemList, int id) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemGetName(favOwner, id); +} + +static int favGetItemNameLength(item_list_t *itemList, int id) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemGetNameLength(favOwner, id); +} + +static char *favGetItemStartup(item_list_t *itemList, int id) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemGetStartup(favOwner, id); +} + +static void favDeleteItem(item_list_t *itemList, int id) +{ + // deleting items not allowed through favourites menu + // a msgBox will display a message indicating this to the user + + return; +} + +static void favRenameItem(item_list_t *itemList, int id, char *newName) +{ + // renaming items not allowed through favourites menu + // a msgBox will display a message indicating this to the user + + return; +} + +static int favGetTextId(item_list_t *itemList) +{ + return _STR_FAV; +} + +static int favGetIconId(item_list_t *itemList) +{ + return FAV_ICON; +} + +static void favLaunchItem(item_list_t *itemList, int id, config_set_t *configSet) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemLaunch(favOwner, id, configSet); +} + +static config_set_t *favGetConfig(item_list_t *itemList, int id) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemGetConfig(favOwner, id); +} + +static int favGetImage(item_list_t *itemList, char *folder, int isRelative, char *value, char *suffix, GSTEXTURE *resultTex, short psm) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + return favOwner->itemGetImage(favOwner, folder, isRelative, value, suffix, resultTex, psm); +} + +static void favCleanUp(item_list_t *itemList, int exception) +{ + if (favItemList.enabled) { + LOG("FAVSUPPORT CleanUp\n"); + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + submenu_list_t *cur = pOwner->menuItem.submenu; + + while (cur != NULL) { + submenu_list_t *next = cur->next; + + // free the text in the submenu item + if (cur->item.text != NULL) { + free(cur->item.text); + cur->item.text = NULL; + } + + // submenu list is freed in submenuDestroy() which is called after this ends + cur = next; + } + } +} + +static void favShutdown(item_list_t *itemList) +{ + favCleanUp(itemList, 0); +} + +static item_list_t favItemList = { + FAV_MODE, -1, 0, 0, MENU_MIN_INACTIVE_FRAMES, FAV_MODE_UPDATE_DELAY, NULL, NULL, &favGetTextId, NULL, &favInit, &favNeedsUpdate, &favUpdateItemList, + &favGetItemCount, NULL, &favGetItemName, &favGetItemNameLength, &favGetItemStartup, &favDeleteItem, &favRenameItem, &favLaunchItem, + &favGetConfig, &favGetImage, &favCleanUp, &favShutdown, NULL, &favGetIconId}; + +unsigned char favGetFlags(item_list_t *itemList) +{ + opl_io_module_t *pOwner = (opl_io_module_t *)itemList->owner; + item_list_t *favOwner = (item_list_t *)pOwner->menuItem.current->item.owner; + + unsigned char flags = 0; + if (favOwner->mode == APP_MODE) + flags |= MODE_FLAG_NO_COMPAT | MODE_FLAG_NO_UPDATE; + + if (favOwner->mode == HDD_MODE) + flags |= MODE_FLAG_COMPAT_DMA; + + return flags; +} + +void writeFavouritesFile(submenu_item_t *items, int size) +{ + char filename[256]; + FILE *file; + int count = size / sizeof(submenu_item_t); + int i; + + snprintf(filename, sizeof(filename), "%sfavourites.bin", configGetDir()); + file = fopen(filename, "wb"); + if (file != NULL) { + for (i = 0; i < count; ++i) { + fwrite(&items[i], sizeof(submenu_item_t), 1, file); + int text_len = strlen(items[i].text) + 1; + fwrite(&text_len, sizeof(int), 1, file); + fwrite(items[i].text, text_len, 1, file); + + // write owner mode, convert to pointer at read file + item_list_t *itemOwner = (item_list_t *)items[i].owner; + fwrite(&itemOwner->mode, sizeof(short int), 1, file); + } + fclose(file); + } +} + +submenu_item_t *readFavouritesFile(int *out_size) +{ + char filename[256]; + FILE *file; + submenu_item_t *items = NULL; + int size, count = 0, i; + + snprintf(filename, sizeof(filename), "%sfavourites.bin", configGetDir()); + file = fopen(filename, "rb"); + if (file != NULL) { + fseek(file, 0, SEEK_END); + size = ftell(file); + rewind(file); + + items = memalign(64, size); + if (items != NULL) { + while (ftell(file) < size) { + fread(&items[count], sizeof(submenu_item_t), 1, file); + int text_len; + fread(&text_len, sizeof(int), 1, file); + items[count].text = memalign(64, text_len); + if (items[count].text != NULL) + fread(items[count].text, text_len, 1, file); + else { + for (i = 0; i < count; ++i) + free(items[i].text); + + free(items); + fclose(file); + return NULL; + } + + // read owner mode and convert it to a pointer + short int mode; + fread(&mode, sizeof(short int), 1, file); + items[count].owner = (void *)getFavouritesOwnerPointer(mode); + + count++; + } + *out_size = count * sizeof(submenu_item_t); + } + + fclose(file); + } + + favItemCount = count; + return items; +} + +void addFavouriteItem(const submenu_item_t *item) +{ + int size; + submenu_item_t *items = readFavouritesFile(&size); + + if (items != NULL) { + // add the new item + int new_size = size + sizeof(submenu_item_t); + submenu_item_t *new_items = memalign(64, new_size); + + if (new_items != NULL) { + memcpy(new_items, items, size); + memcpy((char *)new_items + size, item, sizeof(submenu_item_t)); + new_items[size / sizeof(submenu_item_t)].text = strdup(item->text); + writeFavouritesFile(new_items, new_size); + free(new_items); + } else { + free(items); // free old memory if allocation fails + LOG("Failed to allocate memory for new favourite.\n"); + } + } else { + // if no existing items, create new list + int new_size = sizeof(submenu_item_t); + submenu_item_t *new_items = memalign(64, new_size); + + if (new_items != NULL) { + memcpy(new_items, item, sizeof(submenu_item_t)); + new_items[0].text = strdup(item->text); + writeFavouritesFile(new_items, new_size); + free(new_items); + } else + LOG("Failed to allocate memory for new favourite.\n"); + } +} + +static submenu_item_t *removeFavouriteItem(submenu_item_t *items, int *size, int id, const char *text, int item_size) +{ + int new_size = 0, i; + int count = *size / item_size; + submenu_item_t *new_items = memalign(64, *size); + + if (new_items == NULL) + return NULL; + + for (i = 0; i < count; ++i) { + if (items[i].id != id || (text != NULL && strcmp(items[i].text, text) != 0)) { + memcpy((char *)new_items + new_size, &items[i], item_size); + new_size += item_size; + } else + free(items[i].text); + } + + free(items); + *size = new_size; + + submenu_item_t *reallocated_items = memalign(64, new_size); + if (reallocated_items != NULL) { + memcpy(reallocated_items, new_items, new_size); + free(new_items); + return reallocated_items; + } else { + free(new_items); + return NULL; + } +} + +void removeFavouriteByIdAndText(int id, const char *text) +{ + int size; + submenu_item_t *items = readFavouritesFile(&size); + + if (items != NULL) { + submenu_item_t *updated_items = removeFavouriteItem(items, &size, id, text, sizeof(submenu_item_t)); + if (updated_items != NULL) { + writeFavouritesFile(updated_items, size); + free(updated_items); + } else + LOG("Failed to update favourites.\n"); + } else + LOG("Failed to read favourites file.\n"); +} diff --git a/src/gui.c b/src/gui.c index a8ed33f73..ea46eed8f 100644 --- a/src/gui.c +++ b/src/gui.c @@ -473,8 +473,10 @@ int guiDeviceTypeToIoMode(int deviceType) return ETH_MODE; else if (deviceType == 2) return HDD_MODE; - else + else if (deviceType == 3) return APP_MODE; + else + return FAV_MODE; } int guiIoModeToDeviceType(int ioMode) @@ -492,6 +494,8 @@ int guiIoModeToDeviceType(int ioMode) return 2; case APP_MODE: return 3; + case FAV_MODE: + return 4; default: return 0; } @@ -500,7 +504,7 @@ int guiIoModeToDeviceType(int ioMode) void guiShowConfig() { // configure the enumerations - const char *deviceNames[] = {_l(_STR_BDM_GAMES), _l(_STR_NET_GAMES), _l(_STR_HDD_GAMES), _l(_STR_APPS), NULL}; + const char *deviceNames[] = {_l(_STR_BDM_GAMES), _l(_STR_NET_GAMES), _l(_STR_HDD_GAMES), _l(_STR_APPS), _l(_STR_FAV), NULL}; const char *deviceModes[] = {_l(_STR_OFF), _l(_STR_MANUAL), _l(_STR_AUTO), NULL}; diaSetEnum(diaConfig, CFG_DEFDEVICE, deviceNames); @@ -508,6 +512,7 @@ void guiShowConfig() diaSetEnum(diaConfig, CFG_HDDMODE, deviceModes); diaSetEnum(diaConfig, CFG_ETHMODE, deviceModes); diaSetEnum(diaConfig, CFG_APPMODE, deviceModes); + diaSetEnum(diaConfig, CFG_FAVMODE, deviceModes); diaSetInt(diaConfig, CFG_BDMCACHE, bdmCacheSize); diaSetInt(diaConfig, CFG_HDDCACHE, hddCacheSize); @@ -533,6 +538,7 @@ void guiShowConfig() diaSetInt(diaConfig, CFG_HDDMODE, gHDDStartMode); diaSetInt(diaConfig, CFG_ETHMODE, gETHStartMode); diaSetInt(diaConfig, CFG_APPMODE, gAPPStartMode); + diaSetInt(diaConfig, CFG_FAVMODE, gFAVStartMode); int ret = diaExecuteDialog(diaConfig, -1, 1, &guiUpdater); if (ret) { @@ -552,6 +558,7 @@ void guiShowConfig() diaGetInt(diaConfig, CFG_HDDMODE, &gHDDStartMode); diaGetInt(diaConfig, CFG_ETHMODE, &gETHStartMode); diaGetInt(diaConfig, CFG_APPMODE, &gAPPStartMode); + diaGetInt(diaConfig, CFG_FAVMODE, &gFAVStartMode); diaGetInt(diaConfig, CFG_BDMCACHE, &bdmCacheSize); diaGetInt(diaConfig, CFG_HDDCACHE, &hddCacheSize); diaGetInt(diaConfig, CFG_SMBCACHE, &smbCacheSize); @@ -1000,8 +1007,8 @@ static void guiHandleOp(struct gui_update_t *item) break; case GUI_OP_APPEND_MENU: - result = submenuAppendItem(item->menu.subMenu, item->submenu.icon_id, - item->submenu.text, item->submenu.id, item->submenu.text_id); + result = submenuAppendItem(item->menu.subMenu, item->submenu.icon_id, item->submenu.text, + item->submenu.id, item->submenu.text_id, item->submenu.owner); if (!item->menu.menu->submenu) { // first subitem in list item->menu.menu->submenu = result; diff --git a/src/menusys.c b/src/menusys.c index 972f332ea..f15917a5c 100644 --- a/src/menusys.c +++ b/src/menusys.c @@ -90,6 +90,14 @@ static void menuRenameGame(submenu_list_t **submenu) item_list_t *support = selected_item->item->userdata; + if (support != NULL && support->mode == FAV_MODE) { + char text[128]; + + snprintf(text, sizeof(text), _l(_STR_FAV_MSG), _l(_STR_RENAME)); + guiMsgBox(text, 0, NULL); + return; + } + if (support) { if (support->itemRename) { if (menuCheckParentalLock() == 0) { @@ -124,6 +132,14 @@ static void menuDeleteGame(submenu_list_t **submenu) item_list_t *support = selected_item->item->userdata; + if (support != NULL && support->mode == FAV_MODE) { + char text[128]; + + snprintf(text, sizeof(text), _l(_STR_FAV_MSG), _l(_STR_DELETE)); + guiMsgBox(text, 0, NULL); + return; + } + if (support) { if (support->itemDelete) { if (menuCheckParentalLock() == 0) { @@ -212,19 +228,19 @@ static void menuInitMainMenu(void) submenuDestroy(&mainMenu); // initialize the menu - submenuAppendItem(&mainMenu, -1, NULL, MENU_SETTINGS, _STR_SETTINGS); - submenuAppendItem(&mainMenu, -1, NULL, MENU_GFX_SETTINGS, _STR_GFX_SETTINGS); - submenuAppendItem(&mainMenu, -1, NULL, MENU_AUDIO_SETTINGS, _STR_AUDIO_SETTINGS); - submenuAppendItem(&mainMenu, -1, NULL, MENU_CONTROLLER_SETTINGS, _STR_CONTROLLER_SETTINGS); - submenuAppendItem(&mainMenu, -1, NULL, MENU_OSD_LANGUAGE_SETTINGS, _STR_OSD_SETTINGS); - submenuAppendItem(&mainMenu, -1, NULL, MENU_PARENTAL_LOCK, _STR_PARENLOCKCONFIG); - submenuAppendItem(&mainMenu, -1, NULL, MENU_NET_CONFIG, _STR_NETCONFIG); - submenuAppendItem(&mainMenu, -1, NULL, MENU_NET_UPDATE, _STR_NET_UPDATE); - submenuAppendItem(&mainMenu, -1, NULL, MENU_START_NBD, _STR_STARTNBD); - submenuAppendItem(&mainMenu, -1, NULL, MENU_ABOUT, _STR_ABOUT); - submenuAppendItem(&mainMenu, -1, NULL, MENU_SAVE_CHANGES, _STR_SAVE_CHANGES); - submenuAppendItem(&mainMenu, -1, NULL, MENU_EXIT, _STR_EXIT); - submenuAppendItem(&mainMenu, -1, NULL, MENU_POWER_OFF, _STR_POWEROFF); + submenuAppendItem(&mainMenu, -1, NULL, MENU_SETTINGS, _STR_SETTINGS, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_GFX_SETTINGS, _STR_GFX_SETTINGS, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_AUDIO_SETTINGS, _STR_AUDIO_SETTINGS, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_CONTROLLER_SETTINGS, _STR_CONTROLLER_SETTINGS, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_OSD_LANGUAGE_SETTINGS, _STR_OSD_SETTINGS, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_PARENTAL_LOCK, _STR_PARENLOCKCONFIG, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_NET_CONFIG, _STR_NETCONFIG, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_NET_UPDATE, _STR_NET_UPDATE, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_START_NBD, _STR_STARTNBD, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_ABOUT, _STR_ABOUT, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_SAVE_CHANGES, _STR_SAVE_CHANGES, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_EXIT, _STR_EXIT, NULL); + submenuAppendItem(&mainMenu, -1, NULL, MENU_POWER_OFF, _STR_POWEROFF, NULL); mainMenuCurrent = mainMenu; } @@ -240,21 +256,21 @@ void menuInitGameMenu(void) submenuDestroy(&gameMenu); // initialize the menu - submenuAppendItem(&gameMenu, -1, NULL, GAME_COMPAT_SETTINGS, _STR_COMPAT_SETTINGS); - submenuAppendItem(&gameMenu, -1, NULL, GAME_CHEAT_SETTINGS, _STR_CHEAT_SETTINGS); - submenuAppendItem(&gameMenu, -1, NULL, GAME_GSM_SETTINGS, _STR_GSCONFIG); - submenuAppendItem(&gameMenu, -1, NULL, GAME_VMC_SETTINGS, _STR_VMC_SCREEN); + submenuAppendItem(&gameMenu, -1, NULL, GAME_COMPAT_SETTINGS, _STR_COMPAT_SETTINGS, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_CHEAT_SETTINGS, _STR_CHEAT_SETTINGS, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_GSM_SETTINGS, _STR_GSCONFIG, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_VMC_SETTINGS, _STR_VMC_SCREEN, NULL); #ifdef PADEMU - submenuAppendItem(&gameMenu, -1, NULL, GAME_PADEMU_SETTINGS, _STR_PADEMUCONFIG); - submenuAppendItem(&gameMenu, -1, NULL, GAME_PADMACRO_SETTINGS, _STR_PADMACROCONFIG); + submenuAppendItem(&gameMenu, -1, NULL, GAME_PADEMU_SETTINGS, _STR_PADEMUCONFIG, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_PADMACRO_SETTINGS, _STR_PADMACROCONFIG, NULL); #endif - submenuAppendItem(&gameMenu, -1, NULL, GAME_OSD_LANGUAGE_SETTINGS, _STR_OSD_SETTINGS); - submenuAppendItem(&gameMenu, -1, NULL, GAME_SAVE_CHANGES, _STR_SAVE_CHANGES); - submenuAppendItem(&gameMenu, -1, NULL, GAME_TEST_CHANGES, _STR_TEST); - submenuAppendItem(&gameMenu, -1, NULL, GAME_REMOVE_CHANGES, _STR_REMOVE_ALL_SETTINGS); + submenuAppendItem(&gameMenu, -1, NULL, GAME_OSD_LANGUAGE_SETTINGS, _STR_OSD_SETTINGS, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_SAVE_CHANGES, _STR_SAVE_CHANGES, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_TEST_CHANGES, _STR_TEST, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_REMOVE_CHANGES, _STR_REMOVE_ALL_SETTINGS, NULL); if (gEnableWrite) { - submenuAppendItem(&gameMenu, -1, NULL, GAME_RENAME_GAME, _STR_RENAME); - submenuAppendItem(&gameMenu, -1, NULL, GAME_DELETE_GAME, _STR_DELETE); + submenuAppendItem(&gameMenu, -1, NULL, GAME_RENAME_GAME, _STR_RENAME, NULL); + submenuAppendItem(&gameMenu, -1, NULL, GAME_DELETE_GAME, _STR_DELETE, NULL); } gameMenuCurrent = gameMenu; @@ -266,8 +282,8 @@ void menuInitAppMenu(void) submenuDestroy(&appMenu); // initialize the menu - submenuAppendItem(&appMenu, -1, NULL, 0, _STR_RENAME); - submenuAppendItem(&appMenu, -1, NULL, 1, _STR_DELETE); + submenuAppendItem(&appMenu, -1, NULL, 0, _STR_RENAME, NULL); + submenuAppendItem(&appMenu, -1, NULL, 1, _STR_DELETE, NULL); appMenuCurrent = appMenu; } @@ -404,7 +420,7 @@ void submenuRebuildCache(submenu_list_t *submenu) } } -static submenu_list_t *submenuAllocItem(int icon_id, char *text, int id, int text_id) +static submenu_list_t *submenuAllocItem(int icon_id, char *text, int id, int text_id, void *owner) { submenu_list_t *it = (submenu_list_t *)malloc(sizeof(submenu_list_t)); @@ -416,15 +432,17 @@ static submenu_list_t *submenuAllocItem(int icon_id, char *text, int id, int tex it->item.id = id; it->item.cache_id = NULL; it->item.cache_uid = NULL; + it->item.owner = owner; + it->item.favourited = 0; submenuRebuildCache(it); return it; } -submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *text, int id, int text_id) +submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *text, int id, int text_id, void *owner) { if (*submenu == NULL) { - *submenu = submenuAllocItem(icon_id, text, id, text_id); + *submenu = submenuAllocItem(icon_id, text, id, text_id, owner); return *submenu; } @@ -435,7 +453,7 @@ submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *t cur = cur->next; // create new item - submenu_list_t *newitem = submenuAllocItem(icon_id, text, id, text_id); + submenu_list_t *newitem = submenuAllocItem(icon_id, text, id, text_id, owner); // link cur->next = newitem; @@ -444,6 +462,20 @@ submenu_list_t *submenuAppendItem(submenu_list_t **submenu, int icon_id, char *t return newitem; } +submenu_list_t *submenuFindItemByIdAndText(submenu_list_t *submenu, int id, const char *text) +{ + submenu_list_t *cur = submenu; + + while (cur != NULL) { + if (cur->item.id == id && !strcmp(cur->item.text, text)) + return cur; + + cur = cur->next; + } + + return NULL; +} + static void submenuDestroyItem(submenu_list_t *submenu) { free(submenu->item.cache_id); @@ -918,7 +950,7 @@ void menuHandleInputMenu() if (getKeyOn(KEY_START) || getKeyOn(gSelectButton == KEY_CIRCLE ? KEY_CROSS : KEY_CIRCLE)) { // Check if there is anything to show the user, at all. - if (gAPPStartMode || gETHStartMode || gBDMStartMode || gHDDStartMode) { + if (gAPPStartMode || gETHStartMode || gBDMStartMode || gHDDStartMode || gFAVStartMode) { guiSwitchScreen(GUI_SCREEN_MAIN); refreshMenuPosition(); } @@ -986,6 +1018,8 @@ void menuHandleInputMain() menuFirstPage(); } else if (getKeyOn(KEY_R2)) { // end menuLastPage(); + } else if (getKeyOn(KEY_R3)) { + selected_item->item->fav(selected_item->item); } // Last Played Auto Start diff --git a/src/opl.c b/src/opl.c index cd6098353..9d7bb2fbd 100644 --- a/src/opl.c +++ b/src/opl.c @@ -30,6 +30,7 @@ #include "include/ethsupport.h" #include "include/hddsupport.h" #include "include/appsupport.h" +#include "include/favsupport.h" #include "include/cheatman.h" #include "include/sound.h" @@ -87,6 +88,7 @@ static void clearIOModuleT(opl_io_module_t *mod) mod->menuItem.execCircle = NULL; mod->menuItem.execSquare = NULL; mod->menuItem.execTriangle = NULL; + mod->menuItem.fav = NULL; mod->menuItem.hints = NULL; mod->menuItem.icon_id = -1; mod->menuItem.current = NULL; @@ -133,6 +135,7 @@ int gBDMStartMode; int gHDDStartMode; int gETHStartMode; int gAPPStartMode; +int gFAVStartMode; int bdmCacheSize; int hddCacheSize; int smbCacheSize; @@ -238,6 +241,7 @@ void moduleUpdateMenuInternal(opl_io_module_t *mod, int themeChanged, int langCh menuAddHint(&mod->menuItem, _STR_OPTIONS, TRIANGLE_ICON); menuAddHint(&mod->menuItem, _STR_REFRESH, SELECT_ICON); + menuAddHint(&mod->menuItem, _STR_FAV_HINT, R3_ICON); } // refresh Cache @@ -321,6 +325,9 @@ static void itemExecTriangle(struct menu_item *curMenu) item_list_t *support = curMenu->userdata; if (support) { + if (support->mode == FAV_MODE) + support->flags = favGetFlags(support); + if (!(support->flags & MODE_FLAG_NO_COMPAT)) { if (menuCheckParentalLock() == 0) { menuInitGameMenu(); @@ -337,6 +344,138 @@ static void itemExecTriangle(struct menu_item *curMenu) guiMsgBox("NULL Support object. Please report", 0, NULL); } +static void updateFavouritesMenu(submenu_item_t *item, opl_io_module_t *mdl) +{ + struct gui_update_t *gup = NULL; + gup = guiOpCreate(GUI_OP_APPEND_MENU); + + gup->menu.menu = &mdl->menuItem; + gup->menu.subMenu = &mdl->subMenu; + + gup->submenu.icon_id = item->icon_id; + gup->submenu.id = item->id; + gup->submenu.text = item->text; + gup->submenu.text_id = item->text_id; + gup->submenu.selected = 0; + gup->submenu.owner = (void *)item->owner; + + guiDeferUpdate(gup); + + if (gAutosort) { + gup = guiOpCreate(GUI_OP_SORT); + gup->menu.menu = &mdl->menuItem; + gup->menu.subMenu = &mdl->subMenu; + guiDeferUpdate(gup); + } +} + +item_list_t *getFavouritesOwnerPointer(short int mode) +{ + return list_support[mode].support; +} + +static int validateFavouriteItem(submenu_item_t *item) +{ + item_list_t *itemOwner = (item_list_t *)item->owner; + int i, startMode = itemOwner->mode; + + LOG("Validating favourite: text=%s, id=%d, startMode=%d\n", item->text, item->id, startMode); + + // make sure item from favourites.bin is on a connected device before adding it to the favourites submenu list + // if item was on a bdm device, hot plugging could result in a different mount point.. might need to check them all.. + if (startMode >= BDM_MODE && startMode <= BDM_MODE4) { + for (i = BDM_MODE; i <= BDM_MODE4; i++) { + opl_io_module_t *mdl = &list_support[i]; + + if (mdl->support && mdl->support->enabled) { + submenu_list_t *cur = submenuFindItemByIdAndText(mdl->menuItem.submenu, item->id, item->text); + if (cur != NULL) { + if (startMode != i) { // item found on a new mount point + item->owner = (void *)mdl->support; // update submenu_item owner to the new mode, only in the list.. leave the file alone + LOG("Favourite item found on new mount point, adjusting startMode to %d\n", i); + } + cur->item.favourited = 1; + return 1; + } + } + } + } else { + opl_io_module_t *mdl = &list_support[startMode]; + + if (mdl->support && mdl->support->enabled) { + submenu_list_t *cur = submenuFindItemByIdAndText(mdl->menuItem.submenu, item->id, item->text); + if (cur != NULL) { + cur->item.favourited = 1; + return 1; + } + } + } + + LOG("Favourite item not found %s\n", item->text); + + // can't find the item on a connected device.. keep it in favourites.bin but don't add it to the list for render or execution. + return 0; +} + +void loadFavourites(void) +{ + int size, i; + submenu_item_t *items = readFavouritesFile(&size); + + guiExecDeferredOps(); + clearMenuGameList(&list_support[FAV_MODE]); + + if (items != NULL) { + int count = size / sizeof(submenu_item_t); + for (i = 0; i < count; ++i) { + if (validateFavouriteItem(&items[i])) { + LOG("Favourite found, adding to list\n"); + updateFavouritesMenu(&items[i], &list_support[FAV_MODE]); + } + } + + free(items); + } else + LOG("Failed to load favourites.\n"); +} + +static void itemExecFav(struct menu_item *curMenu) +{ + if (!curMenu->current) + return; + + item_list_t *support = curMenu->userdata; + opl_io_module_t *mdl = &list_support[FAV_MODE]; + + if (!mdl->support || mdl->support->enabled == 0) + return; + + if (curMenu->current->item.favourited || support->mode == FAV_MODE) { + removeFavouriteByIdAndText(curMenu->current->item.id, curMenu->current->item.text); + ioPutRequest(IO_CUSTOM_SIMPLEACTION, &loadFavourites); + curMenu->current->item.favourited = 0; + + // remove favourited flag from source if item removed within fav menu + if (support->mode == FAV_MODE) { + item_list_t *source = curMenu->current->item.owner; + opl_io_module_t *pOwner = (opl_io_module_t *)source->owner; + submenu_list_t *sourceItem = submenuFindItemByIdAndText(pOwner->menuItem.submenu, curMenu->current->item.id, curMenu->current->item.text); + sourceItem->item.favourited = 0; + } + + sfxPlay(SFX_CANCEL); + return; + } + + if (support && support->enabled) { + addFavouriteItem(&curMenu->current->item); + ioPutRequest(IO_CUSTOM_SIMPLEACTION, &loadFavourites); + curMenu->current->item.favourited = 1; + + sfxPlay(SFX_CONFIRM); + } +} + static void initMenuForListSupport(opl_io_module_t *mod) { mod->menuItem.icon_id = mod->support->itemIconId(mod->support); @@ -358,6 +497,7 @@ static void initMenuForListSupport(opl_io_module_t *mod) mod->menuItem.execTriangle = &itemExecTriangle; mod->menuItem.execSquare = &itemExecSquare; mod->menuItem.execCircle = &itemExecCircle; + mod->menuItem.fav = &itemExecFav; mod->menuItem.hints = NULL; @@ -400,6 +540,8 @@ void initSupport(item_list_t *itemList, int mode, int force_reinit) startMode = gHDDStartMode; else if (mode == APP_MODE) startMode = gAPPStartMode; + else if (mode == FAV_MODE) + startMode = gFAVStartMode; if (startMode) { if (!mod->support) { @@ -426,6 +568,7 @@ static void initAllSupport(int force_reinit) initSupport(ethGetObject(0), ETH_MODE, force_reinit || (gNetworkStartup >= ERROR_ETH_SMB_CONN)); initSupport(hddGetObject(0), HDD_MODE, force_reinit); initSupport(appGetObject(0), APP_MODE, force_reinit); + initSupport(favGetObject(0), FAV_MODE, force_reinit); } static void deinitAllSupport(int exception, int modeSelected) @@ -680,6 +823,7 @@ static void updateMenuFromGameList(opl_io_module_t *mdl) gup->submenu.text = mdl->support->itemGetName(mdl->support, i); gup->submenu.text_id = -1; gup->submenu.selected = 0; + gup->submenu.owner = (void *)mdl->support; if (gRememberLastPlayed && temp && strcmp(temp, mdl->support->itemGetStartup(mdl->support, i)) == 0) { gup->submenu.selected = 1; // Select Last Played Game @@ -712,6 +856,9 @@ void menuDeferredUpdate(void *data) // If other modes have been updated, then the apps list should be updated too. if (mod->support->mode != APP_MODE) shouldAppsUpdate = 1; + + if (mod->support->mode != FAV_MODE) + loadFavourites(); } } @@ -934,6 +1081,7 @@ static void _loadConfig() configGetInt(configOPL, CONFIG_OPL_HDD_MODE, &gHDDStartMode); configGetInt(configOPL, CONFIG_OPL_ETH_MODE, &gETHStartMode); configGetInt(configOPL, CONFIG_OPL_APP_MODE, &gAPPStartMode); + configGetInt(configOPL, CONFIG_OPL_FAV_MODE, &gFAVStartMode); configGetInt(configOPL, CONFIG_OPL_ENABLE_ILINK, &gEnableILK); configGetInt(configOPL, CONFIG_OPL_ENABLE_MX4SIO, &gEnableMX4SIO); configGetInt(configOPL, CONFIG_OPL_SFX, &gEnableSFX); @@ -1090,6 +1238,7 @@ static void _saveConfig() configSetInt(configOPL, CONFIG_OPL_HDD_MODE, gHDDStartMode); configSetInt(configOPL, CONFIG_OPL_ETH_MODE, gETHStartMode); configSetInt(configOPL, CONFIG_OPL_APP_MODE, gAPPStartMode); + configSetInt(configOPL, CONFIG_OPL_FAV_MODE, gFAVStartMode); configSetInt(configOPL, CONFIG_OPL_BDM_CACHE, bdmCacheSize); configSetInt(configOPL, CONFIG_OPL_HDD_CACHE, hddCacheSize); configSetInt(configOPL, CONFIG_OPL_SMB_CACHE, smbCacheSize); @@ -1146,7 +1295,7 @@ static void _saveConfig() void applyConfig(int themeID, int langID, int skipDeviceRefresh) { - if (gDefaultDevice < 0 || gDefaultDevice > APP_MODE) + if (gDefaultDevice < 0 || gDefaultDevice > FAV_MODE) gDefaultDevice = APP_MODE; guiUpdateScrollSpeed(); @@ -1726,6 +1875,7 @@ static void setDefaults(void) gHDDStartMode = START_MODE_DISABLED; gETHStartMode = START_MODE_DISABLED; gAPPStartMode = START_MODE_DISABLED; + gFAVStartMode = START_MODE_DISABLED; gEnableILK = 0; gEnableMX4SIO = 0; diff --git a/src/textures.c b/src/textures.c index 853f3e98e..95e4f7572 100644 --- a/src/textures.c +++ b/src/textures.c @@ -20,12 +20,15 @@ extern void *hdd_bd_png; extern void *hdd_png; extern void *eth_png; extern void *app_png; +extern void *fav_png; +extern void *fav_mark_png; extern void *Index_0_png; extern void *Index_1_png; extern void *Index_2_png; extern void *Index_3_png; extern void *Index_4_png; +extern void *R3_png; extern void *left_png; extern void *right_png; extern void *cross_png; @@ -41,8 +44,7 @@ extern void *L1_png; extern void *L2_png; extern void *L3_png; extern void *R1_png; -extern void *R2_png; -extern void *R3_png; */ +extern void *R2_png;*/ extern void *background_png; extern void *info_png; @@ -143,11 +145,14 @@ static texture_t internalDefault[TEXTURES_COUNT] = { {HDD_ICON, "hdd", &hdd_png}, {ETH_ICON, "eth", ð_png}, {APP_ICON, "app", &app_png}, + {FAV_ICON, "fav", &fav_png}, + {FAV_MARK, "fav_mark", &fav_mark_png}, {INDEX_0, "Index_0", &Index_0_png}, {INDEX_1, "Index_1", &Index_1_png}, {INDEX_2, "Index_2", &Index_2_png}, {INDEX_3, "Index_3", &Index_3_png}, {INDEX_4, "Index_4", &Index_4_png}, + {R3_ICON, "R3", &R3_png}, {LEFT_ICON, "left", &left_png}, {RIGHT_ICON, "right", &right_png}, {CROSS_ICON, "cross", &cross_png}, @@ -163,8 +168,7 @@ static texture_t internalDefault[TEXTURES_COUNT] = { {L2_ICON, "L2", &L2_png}, {L3_ICON, "L3", &L3_png}, {R1_ICON, "R1", &R1_png}, - {R2_ICON, "R2", &R2_png}, - {R3_ICON, "R3", &R3_png}, */ + {R2_ICON, "R2", &R2_png}, */ {MAIN_BG, "background", &background_png}, {INFO_BG, "info", &info_png}, {COVER_DEFAULT, "cover", &cover_png}, diff --git a/src/themes.c b/src/themes.c index f3ccdb4f1..aa99be71a 100644 --- a/src/themes.c +++ b/src/themes.c @@ -851,6 +851,7 @@ static void drawItemsList(struct menu_list *menu, struct submenu_list *item, con submenu_list_t *ps = menu->item->pagestart; int others = 0; u64 color; + while (ps && (others++ < itemsList->displayedItems)) { if (ps == item) color = gTheme->selTextColor; @@ -869,6 +870,24 @@ static void drawItemsList(struct menu_list *menu, struct submenu_list *item, con } else fntRenderString(elem->font, elem->posX, posY, elem->aligned, elem->width, elem->height, submenuItemGetText(&ps->item), color); + if (ps->item.favourited) { + int favMarkX = posX; + int favMarkPosY = elem->aligned ? (posY - 4) : (posY + 5); + int textWidth = rmUnScaleX(fntCalcDimensions(elem->font, submenuItemGetText(&ps->item))); + + if (elem->aligned) + favMarkX += ((elem->width - textWidth) >> 1); + + favMarkX += textWidth; + + if (itemsList->decoratorImage) + favMarkX += DECORATOR_SIZE; + + GSTEXTURE *favMark = thmGetTexture(FAV_MARK); + if (favMark && favMark->Mem) + rmDrawPixmap(favMark, favMarkX + 2, favMarkPosY, ALIGN_NONE, 8, 8, elem->scaled, gDefaultCol); + } + posY += MENU_ITEM_HEIGHT; ps = ps->next; }