diff --git a/source/core/linkedlist.c b/source/core/linkedlist.c new file mode 100644 index 0000000..99b1e62 --- /dev/null +++ b/source/core/linkedlist.c @@ -0,0 +1,222 @@ +#include + +#include "linkedlist.h" + +void linked_list_init(linked_list* list) { + list->first = NULL; + list->last = NULL; + list->size = 0; +} + +void linked_list_destroy(linked_list* list) { + linked_list_clear(list); +} + +unsigned int linked_list_size(linked_list* list) { + return list->size; +} + +void linked_list_clear(linked_list* list) { + linked_list_node* node = list->first; + while(node != NULL) { + linked_list_node* next = node->next; + free(node); + node = next; + } + + list->first = NULL; + list->last = NULL; + list->size = 0; +} + +bool linked_list_contains(linked_list* list, void* value) { + linked_list_node* node = list->first; + while(node != NULL) { + if(node->value == value) { + return true; + } + + node = node->next; + } + + return false; +} + +static linked_list_node* linked_list_get_node(linked_list* list, unsigned int index) { + if(index < 0 || index >= list->size) { + return NULL; + } + + linked_list_node* node = NULL; + + if(index > (list->size - 1) / 2) { + node = list->last; + unsigned int pos = list->size - 1; + while(node != NULL && pos != index) { + node = node->prev; + pos--; + } + } else { + node = list->first; + unsigned int pos = 0; + while(node != NULL && pos != index) { + node = node->next; + pos++; + } + } + + return node; +} + +void* linked_list_get(linked_list* list, unsigned int index) { + linked_list_node* node = linked_list_get_node(list, index); + return node != NULL ? node->value : NULL; +} + +bool linked_list_add(linked_list* list, void* value) { + linked_list_node* node = (linked_list_node*) calloc(1, sizeof(linked_list_node)); + if(node == NULL) { + return false; + } + + node->value = value; + node->next = NULL; + + if(list->first == NULL || list->last == NULL) { + node->prev = NULL; + + list->first = node; + list->last = node; + } else { + node->prev = list->last; + + list->last->next = node; + list->last = node; + } + + list->size++; + return true; +} + +bool linked_list_add_at(linked_list* list, unsigned int index, void* value) { + linked_list_node* node = (linked_list_node*) calloc(1, sizeof(linked_list_node)); + if(node == NULL) { + return false; + } + + node->value = value; + + if(index == 0) { + node->prev = NULL; + node->next = list->first; + + list->first = node; + } else { + linked_list_node* prev = linked_list_get_node(list, index - 1); + if(prev == NULL) { + free(node); + return false; + } + + node->prev = prev; + node->next = prev->next; + + prev->next = node; + } + + if(node->next != NULL) { + node->next->prev = node; + } else { + list->last = node; + } + + list->size++; + return true; +} + +static void linked_list_remove_node(linked_list* list, linked_list_node* node) { + if(node->prev != NULL) { + node->prev->next = node->next; + } + + if(node->next != NULL) { + node->next->prev = node->prev; + } + + if(list->first == node) { + list->first = node->next; + } + + if(list->last == node) { + list->last = node->prev; + } + + list->size--; + + free(node); +} + +bool linked_list_remove(linked_list* list, void* value) { + bool found = false; + + linked_list_node* node = list->first; + while(node != NULL) { + linked_list_node* next = node->next; + + if(node->value == value) { + found = true; + + linked_list_remove_node(list, node); + } + + node = next; + } + + return found; +} + +bool linked_list_remove_at(linked_list* list, unsigned int index) { + linked_list_node* node = linked_list_get_node(list, index); + if(node == NULL) { + return false; + } + + linked_list_remove_node(list, node); + return true; +} + +void linked_list_iterate(linked_list* list, linked_list_iter* iter) { + iter->list = list; + linked_list_iter_restart(iter); +} + +void linked_list_iter_restart(linked_list_iter* iter) { + if(iter->list == NULL) { + return; + } + + iter->curr = NULL; + iter->next = iter->list->first; +} + +bool linked_list_iter_has_next(linked_list_iter* iter) { + return iter->next != NULL; +} + +void* linked_list_iter_next(linked_list_iter* iter) { + if(iter->next == NULL) { + return NULL; + } + + iter->curr = iter->next; + iter->next = iter->next->next; + return iter->curr->value; +} + +void linked_list_iter_remove(linked_list_iter* iter) { + if(iter->curr == NULL) { + return; + } + + linked_list_remove_node(iter->list, iter->curr); +} \ No newline at end of file diff --git a/source/core/linkedlist.h b/source/core/linkedlist.h new file mode 100644 index 0000000..e8fe55f --- /dev/null +++ b/source/core/linkedlist.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +typedef struct linked_list_node_s { + struct linked_list_node_s* prev; + struct linked_list_node_s* next; + void* value; +} linked_list_node; + +typedef struct linked_list_s { + linked_list_node* first; + linked_list_node* last; + unsigned int size; +} linked_list; + +typedef struct linked_list_iter_s { + linked_list* list; + linked_list_node* curr; + linked_list_node* next; +} linked_list_iter; + +void linked_list_init(linked_list* list); +void linked_list_destroy(linked_list* list); + +unsigned int linked_list_size(linked_list* list); +void linked_list_clear(linked_list* list); +bool linked_list_contains(linked_list* list, void* value); +void* linked_list_get(linked_list* list, unsigned int index); +bool linked_list_add(linked_list* list, void* value); +bool linked_list_add_at(linked_list* list, unsigned int index, void* value); +bool linked_list_remove(linked_list* list, void* value); +bool linked_list_remove_at(linked_list* list, unsigned int index); + +void linked_list_iterate(linked_list* list, linked_list_iter* iter); + +void linked_list_iter_restart(linked_list_iter* iter); +bool linked_list_iter_has_next(linked_list_iter* iter); +void* linked_list_iter_next(linked_list_iter* iter); +void linked_list_iter_remove(linked_list_iter* iter); \ No newline at end of file diff --git a/source/screen.c b/source/screen.c index 078d2cb..6be0fc4 100644 --- a/source/screen.c +++ b/source/screen.c @@ -547,31 +547,35 @@ void screen_draw_texture_crop(u32 id, float x, float y, float width, float heigh static void screen_get_string_size_internal(float* width, float* height, const char* text, float scaleX, float scaleY, bool oneLine) { float w = 0; - float h = scaleY * fontGetInfo()->lineFeed; + float h = 0; float lineWidth = 0; - const uint8_t* p = (const uint8_t*) text; - uint32_t code = 0; - ssize_t units = -1; - while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) { - p += units; + if(text != NULL) { + h = scaleY * fontGetInfo()->lineFeed; - if(code == '\n') { - if(*p) { - if(lineWidth > w) { - w = lineWidth; + const uint8_t* p = (const uint8_t*) text; + uint32_t code = 0; + ssize_t units = -1; + while(*p && (units = decode_utf8(&code, p)) != -1 && code > 0) { + p += units; + + if(code == '\n') { + if(*p) { + if(lineWidth > w) { + w = lineWidth; + } + + lineWidth = 0; + + if(oneLine) { + break; + } + + h += scaleY * fontGetInfo()->lineFeed; } - - lineWidth = 0; - - if(oneLine) { - break; - } - - h += scaleY * fontGetInfo()->lineFeed; + } else { + lineWidth += scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth; } - } else { - lineWidth += scaleX * fontGetCharWidthInfo(fontGlyphIndexFromCodePoint(code))->charWidth; } } @@ -589,6 +593,10 @@ void screen_get_string_size(float* width, float* height, const char* text, float } void screen_draw_string(const char* text, float x, float y, float scaleX, float scaleY, u32 colorId, bool baseline) { + if(text == NULL) { + return; + } + C3D_TexEnv* env = C3D_GetTexEnv(0); if(env == NULL) { util_panic("Failed to retrieve combiner settings."); diff --git a/source/ui/list.c b/source/ui/list.c index 8fd2978..0aa654e 100644 --- a/source/ui/list.c +++ b/source/ui/list.c @@ -5,27 +5,36 @@ #include "error.h" #include "list.h" #include "../screen.h" +#include "../core/linkedlist.h" typedef struct { void* data; - list_item* items; - u32* itemCount; + linked_list items; u32 selectedIndex; u32 selectionScroll; u64 nextSelectionScrollResetTime; float scrollPos; u32 lastScrollTouchY; u64 nextActionTime; - void (*update)(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched); + void (*update)(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched); void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected); } list_data; static float list_get_item_screen_y(list_data* listData, u32 index) { float y = -listData->scrollPos; - for(u32 i = 0; i < index && i < *listData->itemCount; i++) { + + linked_list_iter iter; + linked_list_iterate(&listData->items, &iter); + + int i = 0; + while(linked_list_iter_has_next(&iter) && i < index) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + float stringHeight; - screen_get_string_size(NULL, &stringHeight, listData->items[i].name, 0.5f, 0.5f); + screen_get_string_size(NULL, &stringHeight, item->name, 0.5f, 0.5f); y += stringHeight; + + i++; } return y; @@ -33,36 +42,47 @@ static float list_get_item_screen_y(list_data* listData, u32 index) { static int list_get_item_at(list_data* listData, float screenY) { float y = -listData->scrollPos; - for(u32 i = 0; i < *listData->itemCount; i++) { + + linked_list_iter iter; + linked_list_iterate(&listData->items, &iter); + + int i = 0; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + float stringHeight; - screen_get_string_size(NULL, &stringHeight, listData->items[i].name, 0.5f, 0.5f); + screen_get_string_size(NULL, &stringHeight, item->name, 0.5f, 0.5f); if(screenY >= y && screenY < y + stringHeight) { - return (int) i; + return i; } y += stringHeight; + + i++; } return -1; } static void list_validate_pos(list_data* listData, float by1, float by2) { - if(listData->items == NULL || listData->itemCount == NULL || *listData->itemCount <= 0 || listData->selectedIndex <= 0) { + u32 size = linked_list_size(&listData->items); + + if(size == 0 || listData->selectedIndex < 0) { listData->selectedIndex = 0; listData->scrollPos = 0; } - if(listData->items != NULL && listData->itemCount != NULL && *listData->itemCount > 0) { - if(listData->selectedIndex > *listData->itemCount - 1) { - listData->selectedIndex = *listData->itemCount - 1; + if(size > 0) { + if(listData->selectedIndex > size - 1) { + listData->selectedIndex = size - 1; listData->scrollPos = 0; } float lastItemHeight; - screen_get_string_size(NULL, &lastItemHeight, listData->items[*listData->itemCount - 1].name, 0.5f, 0.5f); + screen_get_string_size(NULL, &lastItemHeight, ((list_item*) linked_list_get(&listData->items, size - 1))->name, 0.5f, 0.5f); - float lastPageEnd = list_get_item_screen_y(listData, *listData->itemCount - 1); + float lastPageEnd = list_get_item_screen_y(listData, size - 1); if(lastPageEnd < by2 - by1 - lastItemHeight) { listData->scrollPos -= (by2 - by1 - lastItemHeight) - lastPageEnd; } @@ -76,12 +96,14 @@ static void list_validate_pos(list_data* listData, float by1, float by2) { static void list_update(ui_view* view, void* data, float bx1, float by1, float bx2, float by2) { list_data* listData = (list_data*) data; + u32 size = linked_list_size(&listData->items); + bool selectedTouched = false; - if(listData->items != NULL && listData->itemCount != NULL && *listData->itemCount > 0) { + if(size > 0) { list_validate_pos(listData, by1, by2); float itemWidth; - screen_get_string_size(&itemWidth, NULL, listData->items[listData->selectedIndex].name, 0.5f, 0.5f); + screen_get_string_size(&itemWidth, NULL, ((list_item*) linked_list_get(&listData->items, listData->selectedIndex))->name, 0.5f, 0.5f); if(itemWidth > bx2 - bx1) { if(listData->selectionScroll == 0 || listData->selectionScroll >= itemWidth - (bx2 - bx1)) { if(listData->nextSelectionScrollResetTime == 0) { @@ -100,7 +122,7 @@ static void list_update(ui_view* view, void* data, float bx1, float by1, float b u32 lastSelectedIndex = listData->selectedIndex; - if(((hidKeysDown() & KEY_DOWN) || ((hidKeysHeld() & KEY_DOWN) && osGetTime() >= listData->nextActionTime)) && listData->selectedIndex < *listData->itemCount - 1) { + if(((hidKeysDown() & KEY_DOWN) || ((hidKeysHeld() & KEY_DOWN) && osGetTime() >= listData->nextActionTime)) && listData->selectedIndex < size - 1) { listData->selectedIndex++; listData->nextActionTime = osGetTime() + ((hidKeysDown() & KEY_DOWN) ? 500 : 100); } @@ -110,8 +132,8 @@ static void list_update(ui_view* view, void* data, float bx1, float by1, float b listData->nextActionTime = osGetTime() + ((hidKeysDown() & KEY_UP) ? 500 : 100); } - if(((hidKeysDown() & KEY_RIGHT) || ((hidKeysHeld() & KEY_RIGHT) && osGetTime() >= listData->nextActionTime)) && listData->selectedIndex < *listData->itemCount - 1) { - u32 remaining = *listData->itemCount - 1 - listData->selectedIndex; + if(((hidKeysDown() & KEY_RIGHT) || ((hidKeysHeld() & KEY_RIGHT) && osGetTime() >= listData->nextActionTime)) && listData->selectedIndex < size - 1) { + u32 remaining = size - 1 - listData->selectedIndex; listData->selectedIndex += remaining < 13 ? remaining : 13; listData->nextActionTime = osGetTime() + ((hidKeysDown() & KEY_RIGHT) ? 500 : 100); @@ -129,7 +151,7 @@ static void list_update(ui_view* view, void* data, float bx1, float by1, float b listData->nextSelectionScrollResetTime = 0; float itemHeight; - screen_get_string_size(NULL, &itemHeight, listData->items[listData->selectedIndex].name, 0.5f, 0.5f); + screen_get_string_size(NULL, &itemHeight, ((list_item*) linked_list_get(&listData->items, listData->selectedIndex))->name, 0.5f, 0.5f); float itemY = list_get_item_screen_y(listData, listData->selectedIndex); if(itemY + itemHeight > by2 - by1) { @@ -167,7 +189,7 @@ static void list_update(ui_view* view, void* data, float bx1, float by1, float b } if(listData->update != NULL) { - listData->update(view, listData->data, &listData->items, &listData->itemCount, listData->items != NULL && listData->itemCount != NULL && *listData->itemCount > 0 ? &listData->items[listData->selectedIndex] : NULL, selectedTouched); + listData->update(view, listData->data, &listData->items, linked_list_get(&listData->items, listData->selectedIndex), selectedTouched); } } @@ -175,7 +197,7 @@ static void list_draw_top(ui_view* view, void* data, float x1, float y1, float x list_data* listData = (list_data*) data; if(listData->drawTop != NULL) { - listData->drawTop(view, listData->data, x1, y1, x2, y2, listData->items != NULL && listData->itemCount != NULL && *listData->itemCount > 0 ? &listData->items[listData->selectedIndex] : NULL); + listData->drawTop(view, listData->data, x1, y1, x2, y2, linked_list_get(&listData->items, listData->selectedIndex)); } } @@ -184,34 +206,45 @@ static void list_draw_bottom(ui_view* view, void* data, float x1, float y1, floa list_validate_pos(listData, y1, y2); - if(listData->items != NULL && listData->itemCount != NULL) { - float y = y1 - listData->scrollPos; - for(u32 i = 0; i < *listData->itemCount && y < y2; i++) { - float stringHeight; - screen_get_string_size(NULL, &stringHeight, listData->items[i].name, 0.5f, 0.5f); + float y = y1 - listData->scrollPos; - if(y > y1 - stringHeight) { - float x = x1 + 2; - if(i == listData->selectedIndex) { - x -= listData->selectionScroll; - } + linked_list_iter iter; + linked_list_iterate(&listData->items, &iter); - screen_draw_string(listData->items[i].name, x, y, 0.5f, 0.5f, listData->items[i].rgba, false); + u32 i = 0; + while(linked_list_iter_has_next(&iter)) { + if(y > y2) { + break; + } - if(i == listData->selectedIndex) { - u32 selectionOverlayWidth = 0; - u32 selectionOverlayHeight = 0; - screen_get_texture_size(&selectionOverlayWidth, &selectionOverlayHeight, TEXTURE_SELECTION_OVERLAY); - screen_draw_texture(TEXTURE_SELECTION_OVERLAY, (x1 + x2 - selectionOverlayWidth) / 2, y, selectionOverlayWidth, stringHeight); - } + list_item* item = linked_list_iter_next(&iter); + + float stringHeight; + screen_get_string_size(NULL, &stringHeight, item->name, 0.5f, 0.5f); + + if(y > y1 - stringHeight) { + float x = x1 + 2; + if(i == listData->selectedIndex) { + x -= listData->selectionScroll; } - y += stringHeight; + screen_draw_string(item->name, x, y, 0.5f, 0.5f, item->color, false); + + if(i == listData->selectedIndex) { + u32 selectionOverlayWidth = 0; + u32 selectionOverlayHeight = 0; + screen_get_texture_size(&selectionOverlayWidth, &selectionOverlayHeight, TEXTURE_SELECTION_OVERLAY); + screen_draw_texture(TEXTURE_SELECTION_OVERLAY, (x1 + x2 - selectionOverlayWidth) / 2, y, selectionOverlayWidth, stringHeight); + } } + + y += stringHeight; + + i++; } } -void list_display(const char* name, const char* info, void* data, void (*update)(ui_view* view, void* data, list_item** contents, u32** itemCount, list_item* selected, bool selectedTouched), +void list_display(const char* name, const char* info, void* data, void (*update)(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched), void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected)) { list_data* listData = (list_data*) calloc(1, sizeof(list_data)); if(listData == NULL) { @@ -221,8 +254,7 @@ void list_display(const char* name, const char* info, void* data, void (*update) } listData->data = data; - listData->items = NULL; - listData->itemCount = NULL; + linked_list_init(&listData->items); listData->selectedIndex = 0; listData->selectionScroll = 0; listData->nextSelectionScrollResetTime = 0; @@ -249,6 +281,8 @@ void list_display(const char* name, const char* info, void* data, void (*update) } void list_destroy(ui_view* view) { + linked_list_destroy(&((list_data*) view->data)->items); + free(view->data); free(view); } \ No newline at end of file diff --git a/source/ui/list.h b/source/ui/list.h index e233c57..f2f4a26 100644 --- a/source/ui/list.h +++ b/source/ui/list.h @@ -3,13 +3,14 @@ #include #include "ui.h" +#include "../core/linkedlist.h" typedef struct { char name[NAME_MAX]; - u32 rgba; + u32 color; void* data; } list_item; -void list_display(const char* name, const char* info, void* data, void (*update)(ui_view* view, void* data, list_item** contents, u32** itemCount, list_item* selected, bool selectedTouched), +void list_display(const char* name, const char* info, void* data, void (*update)(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched), void (*drawTop)(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected)); void list_destroy(ui_view* view); \ No newline at end of file diff --git a/source/ui/mainmenu.c b/source/ui/mainmenu.c index 7922e87..0a11406 100644 --- a/source/ui/mainmenu.c +++ b/source/ui/mainmenu.c @@ -8,24 +8,19 @@ #include "section/section.h" #include "../screen.h" -#define MAINMENU_ITEM_COUNT 13 - -static u32 mainmenu_item_count = MAINMENU_ITEM_COUNT; -static list_item mainmenu_items[MAINMENU_ITEM_COUNT] = { - {"SD", COLOR_TEXT, files_open_sd}, - {"CTR NAND", COLOR_TEXT, files_open_ctr_nand}, - {"TWL NAND", COLOR_TEXT, files_open_twl_nand}, - {"TWL Photo", COLOR_TEXT, files_open_twl_photo}, - {"TWL Sound", COLOR_TEXT, files_open_twl_sound}, - {"Dump NAND", COLOR_TEXT, dump_nand}, - {"Titles", COLOR_TEXT, titles_open}, - {"Pending Titles", COLOR_TEXT, pendingtitles_open}, - {"Tickets", COLOR_TEXT, tickets_open}, - {"Ext Save Data", COLOR_TEXT, extsavedata_open}, - {"System Save Data", COLOR_TEXT, systemsavedata_open}, - {"Network Install", COLOR_TEXT, networkinstall_open}, - {"QR Code Install", COLOR_TEXT, qrinstall_open}, -}; +static list_item sd = {"SD", COLOR_TEXT, files_open_sd}; +static list_item ctr_nand = {"CTR NAND", COLOR_TEXT, files_open_ctr_nand}; +static list_item twl_nand = {"TWL NAND", COLOR_TEXT, files_open_twl_nand}; +static list_item twl_photo = {"TWL Photo", COLOR_TEXT, files_open_twl_photo}; +static list_item twl_sound = {"TWL Sound", COLOR_TEXT, files_open_twl_sound}; +static list_item dump_nand = {"Dump NAND", COLOR_TEXT, dumpnand_open}; +static list_item titles = {"Titles", COLOR_TEXT, titles_open}; +static list_item pending_titles = {"Pending Titles", COLOR_TEXT, pendingtitles_open}; +static list_item tickets = {"Tickets", COLOR_TEXT, tickets_open}; +static list_item ext_save_data = {"Ext Save Data", COLOR_TEXT, extsavedata_open}; +static list_item system_save_data = {"System Save Data", COLOR_TEXT, systemsavedata_open}; +static list_item network_install = {"Network Install", COLOR_TEXT, networkinstall_open}; +static list_item qr_code_install = {"QR Code Install", COLOR_TEXT, qrinstall_open}; static void mainmenu_draw_top(ui_view* view, void* data, float x1, float y1, float x2, float y2, list_item* selected) { u32 logoWidth; @@ -48,7 +43,7 @@ static void mainmenu_draw_top(ui_view* view, void* data, float x1, float y1, flo screen_draw_string(verString, verX, verY, 0.5f, 0.5f, COLOR_TEXT, false); } -static void mainmenu_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void mainmenu_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { if(hidKeysDown() & KEY_START) { ui_pop(); list_destroy(view); @@ -61,9 +56,20 @@ static void mainmenu_update(ui_view* view, void* data, list_item** items, u32** return; } - if(*itemCount != &mainmenu_item_count || *items != mainmenu_items) { - *itemCount = &mainmenu_item_count; - *items = mainmenu_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &sd); + linked_list_add(items, &ctr_nand); + linked_list_add(items, &twl_nand); + linked_list_add(items, &twl_photo); + linked_list_add(items, &twl_sound); + linked_list_add(items, &dump_nand); + linked_list_add(items, &titles); + linked_list_add(items, &pending_titles); + linked_list_add(items, &tickets); + linked_list_add(items, &ext_save_data); + linked_list_add(items, &system_save_data); + linked_list_add(items, &network_install); + linked_list_add(items, &qr_code_install); } } diff --git a/source/ui/section/action/exportsecurevalue.c b/source/ui/section/action/exportsecurevalue.c index 7b734c4..b9cbcf2 100644 --- a/source/ui/section/action/exportsecurevalue.c +++ b/source/ui/section/action/exportsecurevalue.c @@ -51,6 +51,9 @@ static void action_export_secure_value_update(ui_view* view, void* data, float* } } + ui_pop(); + info_destroy(view); + if(R_SUCCEEDED(res)) { prompt_display("Success", "Secure value exported.", COLOR_TEXT, false, info, NULL, ui_draw_title_info, NULL); } else { diff --git a/source/ui/section/dumpnand.c b/source/ui/section/dumpnand.c index b2c378e..f89e375 100644 --- a/source/ui/section/dumpnand.c +++ b/source/ui/section/dumpnand.c @@ -103,7 +103,7 @@ static void dumpnand_onresponse(ui_view* view, void* data, bool response) { } } -void dump_nand() { +void dumpnand_open() { dump_nand_data* data = (dump_nand_data*) calloc(1, sizeof(dump_nand_data)); if(data == NULL) { error_display(NULL, NULL, NULL, "Failed to allocate dump NAND data."); diff --git a/source/ui/section/extsavedata.c b/source/ui/section/extsavedata.c index 3069741..d80f094 100644 --- a/source/ui/section/extsavedata.c +++ b/source/ui/section/extsavedata.c @@ -6,26 +6,18 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" -#define EXTSAVEDATA_MAX 512 +static list_item browse_user_save_data = {"Browse User Save Data", COLOR_TEXT, action_browse_user_ext_save_data}; +static list_item browse_spotpass_save_data = {"Browse SpotPass Save Data", COLOR_TEXT, action_browse_boss_ext_save_data}; +static list_item delete_save_data = {"Delete Save Data", COLOR_TEXT, action_delete_ext_save_data}; typedef struct { - list_item items[EXTSAVEDATA_MAX]; - u32 count; Handle cancelEvent; bool populated; } extsavedata_data; -#define EXTSAVEDATA_ACTION_COUNT 3 - -static u32 extsavedata_action_count = EXTSAVEDATA_ACTION_COUNT; -static list_item extsavedata_action_items[EXTSAVEDATA_ACTION_COUNT] = { - {"Browse User Save Data", COLOR_TEXT, action_browse_user_ext_save_data}, - {"Browse SpotPass Save Data", COLOR_TEXT, action_browse_boss_ext_save_data}, - {"Delete Save Data", COLOR_TEXT, action_delete_ext_save_data}, -}; - typedef struct { ext_save_data_info* info; bool* populated; @@ -35,7 +27,7 @@ static void extsavedata_action_draw_top(ui_view* view, void* data, float x1, flo ui_draw_ext_save_data_info(view, ((extsavedata_action_data*) data)->info, x1, y1, x2, y2); } -static void extsavedata_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void extsavedata_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { extsavedata_action_data* actionData = (extsavedata_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -60,9 +52,10 @@ static void extsavedata_action_update(ui_view* view, void* data, list_item** ite return; } - if(*itemCount != &extsavedata_action_count || *items != extsavedata_action_items) { - *itemCount = &extsavedata_action_count; - *items = extsavedata_action_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &browse_user_save_data); + linked_list_add(items, &browse_spotpass_save_data); + linked_list_add(items, &delete_save_data); } } @@ -86,7 +79,7 @@ static void extsavedata_draw_top(ui_view* view, void* data, float x1, float y1, } } -static void extsavedata_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void extsavedata_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { extsavedata_data* listData = (extsavedata_data*) data; if(hidKeysDown() & KEY_B) { @@ -100,9 +93,10 @@ static void extsavedata_update(ui_view* view, void* data, list_item** items, u32 } ui_pop(); + + task_clear_ext_save_data(items); list_destroy(view); - task_clear_ext_save_data(listData->items, &listData->count); free(listData); return; } @@ -117,7 +111,7 @@ static void extsavedata_update(ui_view* view, void* data, list_item** items, u32 listData->cancelEvent = 0; } - listData->cancelEvent = task_populate_ext_save_data(listData->items, &listData->count, EXTSAVEDATA_MAX); + listData->cancelEvent = task_populate_ext_save_data(items); listData->populated = true; } @@ -125,11 +119,6 @@ static void extsavedata_update(ui_view* view, void* data, list_item** items, u32 extsavedata_action_open((ext_save_data_info*) selected->data, &listData->populated); return; } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; - } } void extsavedata_open() { diff --git a/source/ui/section/files.c b/source/ui/section/files.c index f9092b7..296a85b 100644 --- a/source/ui/section/files.c +++ b/source/ui/section/files.c @@ -8,14 +8,29 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" #include "../../util.h" +#include "task/task.h" -#define FILES_MAX 1024 +static list_item delete = {"Delete", COLOR_TEXT, action_delete_contents}; +static list_item copy = {"Copy", COLOR_TEXT, action_copy_contents}; +static list_item paste = {"Paste", COLOR_TEXT, action_paste_contents}; + +static list_item install_cia = {"Install CIA", COLOR_TEXT, action_install_cias}; +static list_item install_and_delete_cia = {"Install and delete CIA", COLOR_TEXT, action_install_cias_delete}; + +static list_item install_ticket = {"Install ticket", COLOR_TEXT, action_install_tickets}; + +static list_item delete_all_contents = {"Delete all contents", COLOR_TEXT, action_delete_dir_contents}; + +static list_item install_all_cias = {"Install all CIAs", COLOR_TEXT, action_install_cias}; +static list_item install_and_delete_all_cias = {"Install and delete all CIAs", COLOR_TEXT, action_install_cias_delete}; +static list_item delete_all_cias = {"Delete all CIAs", COLOR_TEXT, action_delete_dir_cias}; + +static list_item install_all_tickets = {"Install all tickets", COLOR_TEXT, action_install_tickets}; typedef struct { - list_item items[FILES_MAX]; - u32 count; Handle cancelEvent; bool populated; @@ -26,84 +41,6 @@ typedef struct { file_info parentDir; } files_data; -#define FILES_ACTION_COUNT 3 - -static u32 files_action_count = FILES_ACTION_COUNT; -static list_item files_action_items[FILES_ACTION_COUNT] = { - {"Delete", COLOR_TEXT, action_delete_contents}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define CIA_FILES_ACTION_COUNT 5 - -static u32 cia_files_action_count = CIA_FILES_ACTION_COUNT; -static list_item cia_files_action_items[CIA_FILES_ACTION_COUNT] = { - {"Install CIA", COLOR_TEXT, action_install_cias}, - {"Install and delete CIA", COLOR_TEXT, action_install_cias_delete}, - {"Delete", COLOR_TEXT, action_delete_contents}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define TICKET_FILES_ACTION_COUNT 4 - -static u32 ticket_files_action_count = TICKET_FILES_ACTION_COUNT; -static list_item ticket_files_action_items[TICKET_FILES_ACTION_COUNT] = { - {"Install ticket", COLOR_TEXT, action_install_tickets}, - {"Delete", COLOR_TEXT, action_delete_contents}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define DIRECTORIES_ACTION_COUNT 4 - -static u32 directories_action_count = DIRECTORIES_ACTION_COUNT; -static list_item directories_action_items[DIRECTORIES_ACTION_COUNT] = { - {"Delete all contents", COLOR_TEXT, action_delete_dir_contents}, - {"Delete", COLOR_TEXT, action_delete_dir}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define CIA_DIRECTORIES_ACTION_COUNT 7 - -static u32 cia_directories_action_count = CIA_DIRECTORIES_ACTION_COUNT; -static list_item cia_directories_action_items[CIA_DIRECTORIES_ACTION_COUNT] = { - {"Install all CIAs", COLOR_TEXT, action_install_cias}, - {"Install and delete all CIAs", COLOR_TEXT, action_install_cias_delete}, - {"Delete all CIAs", COLOR_TEXT, action_delete_dir_cias}, - {"Delete all contents", COLOR_TEXT, action_delete_dir_contents}, - {"Delete", COLOR_TEXT, action_delete_dir}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define TICKET_DIRECTORIES_ACTION_COUNT 5 - -static u32 ticket_directories_action_count = TICKET_DIRECTORIES_ACTION_COUNT; -static list_item ticket_directories_action_items[TICKET_DIRECTORIES_ACTION_COUNT] = { - {"Install all tickets", COLOR_TEXT, action_install_tickets}, - {"Delete all contents", COLOR_TEXT, action_delete_dir_contents}, - {"Delete", COLOR_TEXT, action_delete_dir}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - -#define CIA_TICKET_DIRECTORIES_ACTION_COUNT 8 - -static u32 cia_ticket_directories_action_count = CIA_TICKET_DIRECTORIES_ACTION_COUNT; -static list_item cia_ticket_directories_action_items[CIA_TICKET_DIRECTORIES_ACTION_COUNT] = { - {"Install all CIAs", COLOR_TEXT, action_install_cias}, - {"Install and delete all CIAs", COLOR_TEXT, action_install_cias_delete}, - {"Install all tickets", COLOR_TEXT, action_install_tickets}, - {"Delete all CIAs", COLOR_TEXT, action_delete_dir_cias}, - {"Delete all contents", COLOR_TEXT, action_delete_dir_contents}, - {"Delete", COLOR_TEXT, action_delete_dir}, - {"Copy", COLOR_TEXT, action_copy_contents}, - {"Paste", COLOR_TEXT, action_paste_contents}, -}; - typedef struct { file_info* info; bool* populated; @@ -113,7 +50,7 @@ static void files_action_draw_top(ui_view* view, void* data, float x1, float y1, ui_draw_file_info(view, ((files_action_data*) data)->info, x1, y1, x2, y2); } -static void files_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void files_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { files_action_data* actionData = (files_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -138,45 +75,33 @@ static void files_action_update(ui_view* view, void* data, list_item** items, u3 return; } - if(actionData->info->isDirectory) { - if(actionData->info->containsCias && actionData->info->containsTickets) { - if(*itemCount != &cia_ticket_directories_action_count || *items != cia_ticket_directories_action_items) { - *itemCount = &cia_ticket_directories_action_count; - *items = cia_ticket_directories_action_items; + if(linked_list_size(items) == 0) { + if(actionData->info->isDirectory) { + if(actionData->info->containsCias) { + linked_list_add(items, &install_all_cias); + linked_list_add(items, &install_and_delete_all_cias); + linked_list_add(items, &delete_all_cias); } - } else if(actionData->info->containsCias) { - if(*itemCount != &cia_directories_action_count || *items != cia_directories_action_items) { - *itemCount = &cia_directories_action_count; - *items = cia_directories_action_items; - } - } else if(actionData->info->containsTickets) { - if(*itemCount != &ticket_directories_action_count || *items != ticket_directories_action_items) { - *itemCount = &ticket_directories_action_count; - *items = ticket_directories_action_items; + + if(actionData->info->containsTickets) { + linked_list_add(items, &install_all_tickets); } + + linked_list_add(items, &delete_all_contents); } else { - if(*itemCount != &directories_action_count || *items != directories_action_items) { - *itemCount = &directories_action_count; - *items = directories_action_items; - } - } - } else { - if(actionData->info->isCia) { - if(*itemCount != &cia_files_action_count || *items != cia_files_action_items) { - *itemCount = &cia_files_action_count; - *items = cia_files_action_items; - } - } else if(actionData->info->isTicket) { - if(*itemCount != &ticket_files_action_count || *items != ticket_files_action_items) { - *itemCount = &ticket_files_action_count; - *items = ticket_files_action_items; - } - } else { - if(*itemCount != &files_action_count || *items != files_action_items) { - *itemCount = &files_action_count; - *items = files_action_items; + if(actionData->info->isCia) { + linked_list_add(items, &install_cia); + linked_list_add(items, &install_and_delete_cia); + } + + if(actionData->info->isTicket) { + linked_list_add(items, &install_ticket); } } + + linked_list_add(items, &delete); + linked_list_add(items, ©); + linked_list_add(items, &paste); } } @@ -200,7 +125,7 @@ static void files_draw_top(ui_view* view, void* data, float x1, float y1, float } } -static void files_repopulate(files_data* listData) { +static void files_repopulate(files_data* listData, linked_list* items) { if(listData->cancelEvent != 0) { svcSignalEvent(listData->cancelEvent); while(svcWaitSynchronization(listData->cancelEvent, 0) == 0) { @@ -222,11 +147,11 @@ static void files_repopulate(files_data* listData) { util_get_path_file(listData->parentDir.name, listData->parentDir.path, NAME_MAX); } - listData->cancelEvent = task_populate_files(listData->items, &listData->count, FILES_MAX, &listData->currDir); + listData->cancelEvent = task_populate_files(items, &listData->currDir); listData->populated = true; } -static void files_navigate(files_data* listData, const char* path) { +static void files_navigate(files_data* listData, linked_list* items, const char* path) { strncpy(listData->currDir.path, path, PATH_MAX); util_get_path_file(listData->currDir.name, listData->currDir.path, NAME_MAX); @@ -235,10 +160,10 @@ static void files_navigate(files_data* listData, const char* path) { strncpy(listData->parentDir.path, parentPath, PATH_MAX); util_get_path_file(listData->parentDir.name, listData->parentDir.path, NAME_MAX); - files_repopulate(listData); + files_repopulate(listData, items); } -static void files_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void files_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { files_data* listData = (files_data*) data; if(hidKeysDown() & KEY_B) { @@ -263,13 +188,14 @@ static void files_update(ui_view* view, void* data, list_item** items, u32** ite } ui_pop(); + + task_clear_files(items); list_destroy(view); - task_clear_files(listData->items, &listData->count); free(listData); return; } else { - files_navigate(listData, listData->parentDir.path); + files_navigate(listData, items, listData->parentDir.path); } } @@ -282,7 +208,7 @@ static void files_update(ui_view* view, void* data, list_item** items, u32** ite file_info* fileInfo = (file_info*) selected->data; if(util_is_dir(&listData->archive, fileInfo->path)) { - files_navigate(listData, fileInfo->path); + files_navigate(listData, items, fileInfo->path); } else { files_action_open(fileInfo, &listData->populated); return; @@ -290,12 +216,7 @@ static void files_update(ui_view* view, void* data, list_item** items, u32** ite } if(!listData->populated || (hidKeysDown() & KEY_X)) { - files_repopulate(listData); - } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; + files_repopulate(listData, items); } } diff --git a/source/ui/section/pendingtitles.c b/source/ui/section/pendingtitles.c index 213af2d..3e86b27 100644 --- a/source/ui/section/pendingtitles.c +++ b/source/ui/section/pendingtitles.c @@ -6,25 +6,17 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" -#define PENDINGTITLES_MAX 1024 +static list_item delete_pending_title = {"Delete Pending Title", COLOR_TEXT, action_delete_pending_title}; +static list_item delete_all_pending_titles = {"Delete All Pending Titles", COLOR_TEXT, action_delete_all_pending_titles}; typedef struct { - list_item items[PENDINGTITLES_MAX]; - u32 count; Handle cancelEvent; bool populated; } pendingtitles_data; -#define PENDINGTITLES_ACTION_COUNT 2 - -static u32 pending_titles_action_count = PENDINGTITLES_ACTION_COUNT; -static list_item pending_titles_action_items[PENDINGTITLES_ACTION_COUNT] = { - {"Delete Pending Title", COLOR_TEXT, action_delete_pending_title}, - {"Delete All Pending Titles", COLOR_TEXT, action_delete_all_pending_titles}, -}; - typedef struct { pending_title_info* info; bool* populated; @@ -34,7 +26,7 @@ static void pendingtitles_action_draw_top(ui_view* view, void* data, float x1, f ui_draw_pending_title_info(view, ((pendingtitles_action_data*) data)->info, x1, y1, x2, y2); } -static void pendingtitles_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void pendingtitles_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { pendingtitles_action_data* actionData = (pendingtitles_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -59,9 +51,9 @@ static void pendingtitles_action_update(ui_view* view, void* data, list_item** i return; } - if(*itemCount != &pending_titles_action_count || *items != pending_titles_action_items) { - *itemCount = &pending_titles_action_count; - *items = pending_titles_action_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &delete_pending_title); + linked_list_add(items, &delete_all_pending_titles); } } @@ -85,7 +77,7 @@ static void pendingtitles_draw_top(ui_view* view, void* data, float x1, float y1 } } -static void pendingtitles_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void pendingtitles_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { pendingtitles_data* listData = (pendingtitles_data*) data; if(hidKeysDown() & KEY_B) { @@ -99,9 +91,10 @@ static void pendingtitles_update(ui_view* view, void* data, list_item** items, u } ui_pop(); + + task_clear_pending_titles(items); list_destroy(view); - task_clear_pending_titles(listData->items, &listData->count); free(listData); return; } @@ -116,7 +109,7 @@ static void pendingtitles_update(ui_view* view, void* data, list_item** items, u listData->cancelEvent = 0; } - listData->cancelEvent = task_populate_pending_titles(listData->items, &listData->count, PENDINGTITLES_MAX); + listData->cancelEvent = task_populate_pending_titles(items); listData->populated = true; } @@ -124,11 +117,6 @@ static void pendingtitles_update(ui_view* view, void* data, list_item** items, u pendingtitles_action_open((pending_title_info*) selected->data, &listData->populated); return; } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; - } } void pendingtitles_open() { diff --git a/source/ui/section/section.h b/source/ui/section/section.h index f374225..b6297d1 100644 --- a/source/ui/section/section.h +++ b/source/ui/section/section.h @@ -2,7 +2,7 @@ #include "../ui.h" -void dump_nand(); +void dumpnand_open(); void extsavedata_open(); void files_open(FS_Archive archive); void files_open_sd(); diff --git a/source/ui/section/systemsavedata.c b/source/ui/section/systemsavedata.c index a4de8ef..52e15e3 100644 --- a/source/ui/section/systemsavedata.c +++ b/source/ui/section/systemsavedata.c @@ -6,25 +6,17 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" -#define SYSTEMSAVEDATA_MAX 512 +static list_item browse_save_data = {"Browse Save Data", COLOR_TEXT, action_browse_system_save_data}; +static list_item delete_save_data = {"Delete Save Data", COLOR_TEXT, action_delete_system_save_data}; typedef struct { - list_item items[SYSTEMSAVEDATA_MAX]; - u32 count; Handle cancelEvent; bool populated; } systemsavedata_data; -#define SYSTEMSAVEDATA_ACTION_COUNT 2 - -static u32 systemsavedata_action_count = SYSTEMSAVEDATA_ACTION_COUNT; -static list_item systemsavedata_action_items[SYSTEMSAVEDATA_ACTION_COUNT] = { - {"Browse Save Data", COLOR_TEXT, action_browse_system_save_data}, - {"Delete Save Data", COLOR_TEXT, action_delete_system_save_data}, -}; - typedef struct { system_save_data_info* info; bool* populated; @@ -34,7 +26,7 @@ static void systemsavedata_action_draw_top(ui_view* view, void* data, float x1, ui_draw_system_save_data_info(view, ((systemsavedata_action_data*) data)->info, x1, y1, x2, y2); } -static void systemsavedata_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void systemsavedata_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { systemsavedata_action_data* actionData = (systemsavedata_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -59,9 +51,9 @@ static void systemsavedata_action_update(ui_view* view, void* data, list_item** return; } - if(*itemCount != &systemsavedata_action_count || *items != systemsavedata_action_items) { - *itemCount = &systemsavedata_action_count; - *items = systemsavedata_action_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &browse_save_data); + linked_list_add(items, &delete_save_data); } } @@ -85,7 +77,7 @@ static void systemsavedata_draw_top(ui_view* view, void* data, float x1, float y } } -static void systemsavedata_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void systemsavedata_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { systemsavedata_data* listData = (systemsavedata_data*) data; if(hidKeysDown() & KEY_B) { @@ -99,9 +91,10 @@ static void systemsavedata_update(ui_view* view, void* data, list_item** items, } ui_pop(); + + task_clear_system_save_data(items); list_destroy(view); - task_clear_system_save_data(listData->items, &listData->count); free(listData); return; } @@ -116,7 +109,7 @@ static void systemsavedata_update(ui_view* view, void* data, list_item** items, listData->cancelEvent = 0; } - listData->cancelEvent = task_populate_system_save_data(listData->items, &listData->count, SYSTEMSAVEDATA_MAX); + listData->cancelEvent = task_populate_system_save_data(items); listData->populated = true; } @@ -124,11 +117,6 @@ static void systemsavedata_update(ui_view* view, void* data, list_item** items, systemsavedata_action_open((system_save_data_info*) selected->data, &listData->populated); return; } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; - } } void systemsavedata_open() { diff --git a/source/ui/section/task/listextsavedata.c b/source/ui/section/task/listextsavedata.c index 7872a4d..2a448e0 100644 --- a/source/ui/section/task/listextsavedata.c +++ b/source/ui/section/task/listextsavedata.c @@ -12,10 +12,10 @@ #include "../../../util.h" #include "task.h" +#define MAX_EXT_SAVE_DATA 512 + typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; Handle cancelEvent; } populate_ext_save_data_data; @@ -24,69 +24,74 @@ static Result task_populate_ext_save_data_from(populate_ext_save_data_data* data Result res = 0; u32 extSaveDataCount = 0; - u64* extSaveDataIds = (u64*) calloc(data->max, sizeof(u64)); + u64* extSaveDataIds = (u64*) calloc(MAX_EXT_SAVE_DATA, sizeof(u64)); if(extSaveDataIds != NULL) { - if(R_SUCCEEDED(res = FSUSER_EnumerateExtSaveData(&extSaveDataCount, data->max, mediaType, 8, mediaType == MEDIATYPE_NAND, (u8*) extSaveDataIds))) { + if(R_SUCCEEDED(res = FSUSER_EnumerateExtSaveData(&extSaveDataCount, MAX_EXT_SAVE_DATA, mediaType, 8, mediaType == MEDIATYPE_NAND, (u8*) extSaveDataIds))) { qsort(extSaveDataIds, extSaveDataCount, sizeof(u64), util_compare_u64); SMDH smdh; - for(u32 i = 0; i < extSaveDataCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < extSaveDataCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } - ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info)); - if(extSaveDataInfo != NULL) { - extSaveDataInfo->mediaType = mediaType; - extSaveDataInfo->extSaveDataId = extSaveDataIds[i]; - extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND; - extSaveDataInfo->hasMeta = false; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) calloc(1, sizeof(ext_save_data_info)); + if(extSaveDataInfo != NULL) { + extSaveDataInfo->mediaType = mediaType; + extSaveDataInfo->extSaveDataId = extSaveDataIds[i]; + extSaveDataInfo->shared = mediaType == MEDIATYPE_NAND; + extSaveDataInfo->hasMeta = false; - list_item* item = &data->items[*data->count]; + FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]}; + u32 smdhBytesRead = 0; + if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) &smdh)) && smdhBytesRead == sizeof(SMDH)) { + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); - FS_ExtSaveDataInfo info = {.mediaType = mediaType, .saveId = extSaveDataIds[i]}; - u32 smdhBytesRead = 0; - if(R_SUCCEEDED(FSUSER_ReadExtSaveDataIcon(&smdhBytesRead, info, sizeof(SMDH), (u8*) &smdh)) && smdhBytesRead == sizeof(SMDH)) { - u8 systemLanguage = CFG_LANGUAGE_EN; - CFGU_GetSystemLanguage(&systemLanguage); + utf16_to_utf8((uint8_t*) item->name, smdh.titles[systemLanguage].shortDescription, NAME_MAX - 1); - utf16_to_utf8((uint8_t*) item->name, smdh.titles[systemLanguage].shortDescription, NAME_MAX - 1); - - extSaveDataInfo->hasMeta = true; - utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1); - utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1); - utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh.titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1); - extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); - } - - bool empty = strlen(item->name) == 0; - if(!empty) { - empty = true; - - char* curr = item->name; - while(*curr) { - if(*curr != ' ') { - empty = false; - break; - } - - curr++; + extSaveDataInfo->hasMeta = true; + utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(extSaveDataInfo->meta.shortDescription) - 1); + utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(extSaveDataInfo->meta.longDescription) - 1); + utf16_to_utf8((uint8_t*) extSaveDataInfo->meta.publisher, smdh.titles[systemLanguage].publisher, sizeof(extSaveDataInfo->meta.publisher) - 1); + extSaveDataInfo->meta.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); } + + bool empty = strlen(item->name) == 0; + if(!empty) { + empty = true; + + char* curr = item->name; + while(*curr) { + if(*curr != ' ') { + empty = false; + break; + } + + curr++; + } + } + + if(empty) { + snprintf(item->name, NAME_MAX, "%016llX", extSaveDataIds[i]); + } + + if(mediaType == MEDIATYPE_NAND) { + item->color = COLOR_NAND; + } else if(mediaType == MEDIATYPE_SD) { + item->color = COLOR_SD; + } + + item->data = extSaveDataInfo; + + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; } - - if(empty) { - snprintf(item->name, NAME_MAX, "%016llX", extSaveDataIds[i]); - } - - if(mediaType == MEDIATYPE_NAND) { - item->rgba = COLOR_NAND; - } else if(mediaType == MEDIATYPE_SD) { - item->rgba = COLOR_SD; - } - - item->data = extSaveDataInfo; - - (*data->count)++; } else { res = R_FBI_OUT_OF_MEMORY; } @@ -113,36 +118,38 @@ static void task_populate_ext_save_data_thread(void* arg) { free(data); } -void task_clear_ext_save_data(list_item* items, u32* count) { - if(items == NULL || count == NULL || *count == 0) { +void task_clear_ext_save_data(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) items[i].data; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + ext_save_data_info* extSaveDataInfo = (ext_save_data_info*) item->data; if(extSaveDataInfo->hasMeta) { screen_unload_texture(extSaveDataInfo->meta.texture); } - free(items[i].data); - items[i].data = NULL; + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_ext_save_data(list_item* items, u32* count, u32 max) { - if(items == NULL || count == NULL || max == 0) { +Handle task_populate_ext_save_data(linked_list* items) { + if(items == NULL) { return 0; } - task_clear_ext_save_data(items, count); + task_clear_ext_save_data(items); populate_ext_save_data_data* data = (populate_ext_save_data_data*) calloc(1, sizeof(populate_ext_save_data_data)); if(data == NULL) { @@ -152,8 +159,6 @@ Handle task_populate_ext_save_data(list_item* items, u32* count, u32 max) { } data->items = items; - data->count = count; - data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { diff --git a/source/ui/section/task/listfiles.c b/source/ui/section/task/listfiles.c index 048c870..492c8ee 100644 --- a/source/ui/section/task/listfiles.c +++ b/source/ui/section/task/listfiles.c @@ -12,14 +12,13 @@ #include "../../../screen.h" #include "task.h" +#define MAX_FILES 1024 + typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; + file_info* dir; Handle cancelEvent; - - file_info* dir; } populate_files_data; static void task_populate_files_thread(void* arg) { @@ -34,13 +33,13 @@ static void task_populate_files_thread(void* arg) { Handle dirHandle = 0; if(R_SUCCEEDED(res = FSUSER_OpenDirectory(&dirHandle, *data->dir->archive, *fsPath))) { u32 entryCount = 0; - FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(data->max, sizeof(FS_DirectoryEntry)); + FS_DirectoryEntry* entries = (FS_DirectoryEntry*) calloc(MAX_FILES, sizeof(FS_DirectoryEntry)); if(entries != NULL) { - if(R_SUCCEEDED(res = FSDIR_Read(dirHandle, &entryCount, data->max, entries)) && entryCount > 0) { + if(R_SUCCEEDED(res = FSDIR_Read(dirHandle, &entryCount, MAX_FILES, entries)) && entryCount > 0) { qsort(entries, entryCount, sizeof(FS_DirectoryEntry), util_compare_directory_entries); SMDH smdh; - for(u32 i = 0; i < entryCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < entryCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } @@ -49,91 +48,96 @@ static void task_populate_files_thread(void* arg) { continue; } - file_info* fileInfo = (file_info*) calloc(1, sizeof(file_info)); - if(fileInfo != NULL) { - fileInfo->archive = data->dir->archive; - utf16_to_utf8((uint8_t*) fileInfo->name, entries[i].name, NAME_MAX - 1); - fileInfo->containsCias = false; - fileInfo->size = 0; - fileInfo->isCia = false; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + file_info* fileInfo = (file_info*) calloc(1, sizeof(file_info)); + if(fileInfo != NULL) { + fileInfo->archive = data->dir->archive; + utf16_to_utf8((uint8_t*) fileInfo->name, entries[i].name, NAME_MAX - 1); + fileInfo->containsCias = false; + fileInfo->size = 0; + fileInfo->isCia = false; - list_item* item = &data->items[*data->count]; + if(entries[i].attributes & FS_ATTRIBUTE_DIRECTORY) { + item->color = COLOR_DIRECTORY; - if(entries[i].attributes & FS_ATTRIBUTE_DIRECTORY) { - item->rgba = COLOR_DIRECTORY; + snprintf(fileInfo->path, PATH_MAX, "%s%s/", data->dir->path, fileInfo->name); + fileInfo->isDirectory = true; + } else { + item->color = COLOR_TEXT; - snprintf(fileInfo->path, PATH_MAX, "%s%s/", data->dir->path, fileInfo->name); - fileInfo->isDirectory = true; - } else { - item->rgba = COLOR_TEXT; + snprintf(fileInfo->path, PATH_MAX, "%s%s", data->dir->path, fileInfo->name); + fileInfo->isDirectory = false; - snprintf(fileInfo->path, PATH_MAX, "%s%s", data->dir->path, fileInfo->name); - fileInfo->isDirectory = false; + FS_Path* fileFsPath = util_make_path_utf8(fileInfo->path); + if(fileFsPath != NULL) { + Handle fileHandle; + if(R_SUCCEEDED(FSUSER_OpenFile(&fileHandle, *data->dir->archive, *fileFsPath, FS_OPEN_READ, 0))) { + FSFILE_GetSize(fileHandle, &fileInfo->size); - FS_Path* fileFsPath = util_make_path_utf8(fileInfo->path); - if(fileFsPath != NULL) { - Handle fileHandle; - if(R_SUCCEEDED(FSUSER_OpenFile(&fileHandle, *data->dir->archive, *fileFsPath, FS_OPEN_READ, 0))) { - FSFILE_GetSize(fileHandle, &fileInfo->size); + size_t len = strlen(fileInfo->path); + if(len > 4) { + if(strcasecmp(&fileInfo->path[len - 4], ".cia") == 0) { + AM_TitleEntry titleEntry; + if(R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_SD, &titleEntry, fileHandle))) { + data->dir->containsCias = true; - size_t len = strlen(fileInfo->path); - if(len > 4) { - if(strcasecmp(&fileInfo->path[len - 4], ".cia") == 0) { - AM_TitleEntry titleEntry; - if(R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_SD, &titleEntry, fileHandle))) { - data->dir->containsCias = true; - - fileInfo->isCia = true; - fileInfo->ciaInfo.titleId = titleEntry.titleID; - fileInfo->ciaInfo.version = titleEntry.version; - fileInfo->ciaInfo.installedSize = titleEntry.size; - fileInfo->ciaInfo.hasMeta = false; - - if(((titleEntry.titleID >> 32) & 0x8010) != 0 && R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_NAND, &titleEntry, fileHandle))) { + fileInfo->isCia = true; + fileInfo->ciaInfo.titleId = titleEntry.titleID; + fileInfo->ciaInfo.version = titleEntry.version; fileInfo->ciaInfo.installedSize = titleEntry.size; + fileInfo->ciaInfo.hasMeta = false; + + if(((titleEntry.titleID >> 32) & 0x8010) != 0 && R_SUCCEEDED(AM_GetCiaFileInfo(MEDIATYPE_NAND, &titleEntry, fileHandle))) { + fileInfo->ciaInfo.installedSize = titleEntry.size; + } + + if(R_SUCCEEDED(AM_GetCiaIcon(&smdh, fileHandle))) { + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); + + fileInfo->ciaInfo.hasMeta = true; + utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.meta.shortDescription) - 1); + utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.meta.longDescription) - 1); + utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.publisher, smdh.titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.meta.publisher) - 1); + fileInfo->ciaInfo.meta.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); + } } + } else if(strcasecmp(&fileInfo->path[len - 4], ".tik") == 0) { + u32 bytesRead = 0; - if(R_SUCCEEDED(AM_GetCiaIcon(&smdh, fileHandle))) { - u8 systemLanguage = CFG_LANGUAGE_EN; - CFGU_GetSystemLanguage(&systemLanguage); + u8 sigType = 0; + if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 3, &sigType, sizeof(sigType))) && bytesRead == sizeof(sigType) && sigType <= 5) { + static u32 dataOffsets[6] = {0x240, 0x140, 0x80, 0x240, 0x140, 0x80}; + static u32 titleIdOffset = 0x9C; - fileInfo->ciaInfo.hasMeta = true; - utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.shortDescription, smdh.titles[systemLanguage].shortDescription, sizeof(fileInfo->ciaInfo.meta.shortDescription) - 1); - utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.longDescription, smdh.titles[systemLanguage].longDescription, sizeof(fileInfo->ciaInfo.meta.longDescription) - 1); - utf16_to_utf8((uint8_t*) fileInfo->ciaInfo.meta.publisher, smdh.titles[systemLanguage].publisher, sizeof(fileInfo->ciaInfo.meta.publisher) - 1); - fileInfo->ciaInfo.meta.texture = screen_load_texture_tiled_auto(smdh.largeIcon, sizeof(smdh.largeIcon), 48, 48, GPU_RGB565, false); - } - } - } else if(strcasecmp(&fileInfo->path[len - 4], ".tik") == 0) { - u32 bytesRead = 0; + u64 titleId = 0; + if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, dataOffsets[sigType] + titleIdOffset, &titleId, sizeof(titleId))) && bytesRead == sizeof(titleId)) { + data->dir->containsTickets = true; - u8 sigType = 0; - if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 3, &sigType, sizeof(sigType))) && bytesRead == sizeof(sigType) && sigType <= 5) { - static u32 dataOffsets[6] = {0x240, 0x140, 0x80, 0x240, 0x140, 0x80}; - static u32 titleIdOffset = 0x9C; - - u64 titleId = 0; - if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, dataOffsets[sigType] + titleIdOffset, &titleId, sizeof(titleId))) && bytesRead == sizeof(titleId)) { - data->dir->containsTickets = true; - - fileInfo->isTicket = true; - fileInfo->ticketInfo.titleId = __builtin_bswap64(titleId); + fileInfo->isTicket = true; + fileInfo->ticketInfo.titleId = __builtin_bswap64(titleId); + } } } } + + FSFILE_Close(fileHandle); } - FSFILE_Close(fileHandle); + util_free_path_utf8(fileFsPath); } - - util_free_path_utf8(fileFsPath); } + + strncpy(item->name, fileInfo->name, NAME_MAX); + item->data = fileInfo; + + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; } - - strncpy(item->name, fileInfo->name, NAME_MAX); - item->data = fileInfo; - - (*data->count)++; } else { res = R_FBI_OUT_OF_MEMORY; } @@ -161,36 +165,38 @@ static void task_populate_files_thread(void* arg) { free(data); } -void task_clear_files(list_item* items, u32* count) { - if(items == NULL || count == NULL) { +void task_clear_files(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - file_info* fileInfo = (file_info*) items[i].data; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + file_info* fileInfo = (file_info*) item->data; if(fileInfo->isCia && fileInfo->ciaInfo.hasMeta) { screen_unload_texture(fileInfo->ciaInfo.meta.texture); } - free(items[i].data); - items[i].data = NULL; + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_files(list_item* items, u32* count, u32 max, file_info* dir) { - if(items == NULL || count == NULL || max == 0 || dir == NULL) { +Handle task_populate_files(linked_list* items, file_info* dir) { + if(items == NULL || dir == NULL) { return 0; } - task_clear_files(items, count); + task_clear_files(items); populate_files_data* data = (populate_files_data*) calloc(1, sizeof(populate_files_data)); if(data == NULL) { @@ -200,8 +206,6 @@ Handle task_populate_files(list_item* items, u32* count, u32 max, file_info* dir } data->items = items; - data->count = count; - data->max = max; data->dir = dir; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); diff --git a/source/ui/section/task/listpendingtitles.c b/source/ui/section/task/listpendingtitles.c index 930bf0a..06126db 100644 --- a/source/ui/section/task/listpendingtitles.c +++ b/source/ui/section/task/listpendingtitles.c @@ -2,7 +2,6 @@ #include #include #include -#include #include <3ds.h> @@ -13,9 +12,7 @@ #include "task.h" typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; Handle cancelEvent; } populate_pending_titles_data; @@ -33,28 +30,34 @@ static Result task_populate_pending_titles_from(populate_pending_titles_data* da AM_PendingTitleEntry* pendingTitleInfos = (AM_PendingTitleEntry*) calloc(pendingTitleCount, sizeof(AM_PendingTitleEntry)); if(pendingTitleInfos != NULL) { if(R_SUCCEEDED(res = AM_GetPendingTitleInfo(pendingTitleCount, mediaType, pendingTitleIds, pendingTitleInfos))) { - for(u32 i = 0; i < pendingTitleCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < pendingTitleCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } - pending_title_info* pendingTitleInfo = (pending_title_info*) calloc(1, sizeof(pending_title_info)); - if(pendingTitleInfo != NULL) { - pendingTitleInfo->mediaType = mediaType; - pendingTitleInfo->titleId = pendingTitleIds[i]; - pendingTitleInfo->version = pendingTitleInfos[i].version; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + pending_title_info* pendingTitleInfo = (pending_title_info*) calloc(1, sizeof(pending_title_info)); + if(pendingTitleInfo != NULL) { + pendingTitleInfo->mediaType = mediaType; + pendingTitleInfo->titleId = pendingTitleIds[i]; + pendingTitleInfo->version = pendingTitleInfos[i].version; - list_item* item = &data->items[*data->count]; - snprintf(item->name, NAME_MAX, "%016llX", pendingTitleIds[i]); - if(mediaType == MEDIATYPE_NAND) { - item->rgba = COLOR_NAND; - } else if(mediaType == MEDIATYPE_SD) { - item->rgba = COLOR_SD; + snprintf(item->name, NAME_MAX, "%016llX", pendingTitleIds[i]); + if(mediaType == MEDIATYPE_NAND) { + item->color = COLOR_NAND; + } else if(mediaType == MEDIATYPE_SD) { + item->color = COLOR_SD; + } + + item->data = pendingTitleInfo; + + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; } - - item->data = pendingTitleInfo; - - (*data->count)++; } else { res = R_FBI_OUT_OF_MEMORY; } @@ -88,31 +91,33 @@ static void task_populate_pending_titles_thread(void* arg) { free(data); } -void task_clear_pending_titles(list_item* items, u32* count) { - if(items == NULL || count == NULL) { +void task_clear_pending_titles(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - free(items[i].data); - items[i].data = NULL; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_pending_titles(list_item* items, u32* count, u32 max) { - if(items == NULL || count == NULL || max == 0) { +Handle task_populate_pending_titles(linked_list* items) { + if(items == NULL) { return 0; } - task_clear_pending_titles(items, count); + task_clear_pending_titles(items); populate_pending_titles_data* data = (populate_pending_titles_data*) calloc(1, sizeof(populate_pending_titles_data)); if(data == NULL) { @@ -122,8 +127,6 @@ Handle task_populate_pending_titles(list_item* items, u32* count, u32 max) { } data->items = items; - data->count = count; - data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { diff --git a/source/ui/section/task/listsystemsavedata.c b/source/ui/section/task/listsystemsavedata.c index 9e83fe4..169d1e8 100644 --- a/source/ui/section/task/listsystemsavedata.c +++ b/source/ui/section/task/listsystemsavedata.c @@ -12,10 +12,10 @@ #include "../../../util.h" #include "task.h" +#define MAX_SYSTEM_SAVE_DATA 512 + typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; Handle cancelEvent; } populate_system_save_data_data; @@ -26,26 +26,32 @@ static void task_populate_system_save_data_thread(void* arg) { Result res = 0; u32 systemSaveDataCount = 0; - u32* systemSaveDataIds = (u32*) calloc(data->max, sizeof(u32)); + u32* systemSaveDataIds = (u32*) calloc(MAX_SYSTEM_SAVE_DATA, sizeof(u32)); if(systemSaveDataIds != NULL) { - if(R_SUCCEEDED(res = FSUSER_EnumerateSystemSaveData(&systemSaveDataCount, data->max * sizeof(u32), systemSaveDataIds))) { + if(R_SUCCEEDED(res = FSUSER_EnumerateSystemSaveData(&systemSaveDataCount, MAX_SYSTEM_SAVE_DATA * sizeof(u32), systemSaveDataIds))) { qsort(systemSaveDataIds, systemSaveDataCount, sizeof(u32), util_compare_u32); - for(u32 i = 0; i < systemSaveDataCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < systemSaveDataCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } - system_save_data_info* systemSaveDataInfo = (system_save_data_info*) calloc(1, sizeof(system_save_data_info)); - if(systemSaveDataInfo != NULL) { - systemSaveDataInfo->systemSaveDataId = systemSaveDataIds[i]; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + system_save_data_info* systemSaveDataInfo = (system_save_data_info*) calloc(1, sizeof(system_save_data_info)); + if(systemSaveDataInfo != NULL) { + systemSaveDataInfo->systemSaveDataId = systemSaveDataIds[i]; - list_item* item = &data->items[*data->count]; - snprintf(item->name, NAME_MAX, "%08lX", systemSaveDataIds[i]); - item->rgba = COLOR_TEXT; - item->data = systemSaveDataInfo; + snprintf(item->name, NAME_MAX, "%08lX", systemSaveDataIds[i]); + item->color = COLOR_TEXT; + item->data = systemSaveDataInfo; - (*data->count)++; + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; + } } else { res = R_FBI_OUT_OF_MEMORY; } @@ -65,31 +71,33 @@ static void task_populate_system_save_data_thread(void* arg) { free(data); } -void task_clear_system_save_data(list_item* items, u32* count) { - if(items == NULL || count == NULL) { +void task_clear_system_save_data(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - free(items[i].data); - items[i].data = NULL; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_system_save_data(list_item* items, u32* count, u32 max) { - if(items == NULL || count == NULL || max == 0) { +Handle task_populate_system_save_data(linked_list* items) { + if(items == NULL) { return 0; } - task_clear_system_save_data(items, count); + task_clear_system_save_data(items); populate_system_save_data_data* data = (populate_system_save_data_data*) calloc(1, sizeof(populate_system_save_data_data)); if(data == NULL) { @@ -99,8 +107,6 @@ Handle task_populate_system_save_data(list_item* items, u32* count, u32 max) { } data->items = items; - data->count = count; - data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { diff --git a/source/ui/section/task/listtickets.c b/source/ui/section/task/listtickets.c index 4f138a1..d588afd 100644 --- a/source/ui/section/task/listtickets.c +++ b/source/ui/section/task/listtickets.c @@ -13,9 +13,7 @@ #include "task.h" typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; Handle cancelEvent; } populate_tickets_data; @@ -32,21 +30,27 @@ static void task_populate_tickets_thread(void* arg) { if(R_SUCCEEDED(res = AM_GetTicketList(&ticketCount, ticketCount, 0, ticketIds))) { qsort(ticketIds, ticketCount, sizeof(u64), util_compare_u64); - for(u32 i = 0; i < ticketCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < ticketCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } - ticket_info* ticketInfo = (ticket_info*) calloc(1, sizeof(ticket_info)); - if(ticketInfo != NULL) { - ticketInfo->titleId = ticketIds[i]; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + ticket_info* ticketInfo = (ticket_info*) calloc(1, sizeof(ticket_info)); + if(ticketInfo != NULL) { + ticketInfo->titleId = ticketIds[i]; - list_item* item = &data->items[*data->count]; - snprintf(item->name, NAME_MAX, "%016llX", ticketIds[i]); - item->rgba = COLOR_TEXT; - item->data = ticketInfo; + snprintf(item->name, NAME_MAX, "%016llX", ticketIds[i]); + item->color = COLOR_TEXT; + item->data = ticketInfo; - (*data->count)++; + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; + } } else { res = R_FBI_OUT_OF_MEMORY; } @@ -67,31 +71,33 @@ static void task_populate_tickets_thread(void* arg) { free(data); } -void task_clear_tickets(list_item* items, u32* count) { - if(items == NULL || count == NULL) { +void task_clear_tickets(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - free(items[i].data); - items[i].data = NULL; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_tickets(list_item* items, u32* count, u32 max) { - if(items == NULL || count == NULL || max == 0) { +Handle task_populate_tickets(linked_list* items) { + if(items == NULL) { return 0; } - task_clear_tickets(items, count); + task_clear_tickets(items); populate_tickets_data* data = (populate_tickets_data*) calloc(1, sizeof(populate_tickets_data)); if(data == NULL) { @@ -101,8 +107,6 @@ Handle task_populate_tickets(list_item* items, u32* count, u32 max) { } data->items = items; - data->count = count; - data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { diff --git a/source/ui/section/task/listtitles.c b/source/ui/section/task/listtitles.c index a5b58b3..c51c8d6 100644 --- a/source/ui/section/task/listtitles.c +++ b/source/ui/section/task/listtitles.c @@ -14,9 +14,7 @@ #include "task.h" typedef struct { - list_item* items; - u32* count; - u32 max; + linked_list* items; Handle cancelEvent; } populate_titles_data; @@ -26,80 +24,85 @@ static Result task_populate_titles_add_ctr(populate_titles_data* data, FS_MediaT AM_TitleEntry entry; if(R_SUCCEEDED(res = AM_GetTitleInfo(mediaType, 1, &titleId, &entry))) { - title_info* titleInfo = (title_info*) calloc(1, sizeof(title_info)); - if(titleInfo != NULL) { - titleInfo->mediaType = mediaType; - titleInfo->titleId = titleId; - AM_GetTitleProductCode(mediaType, titleId, titleInfo->productCode); - titleInfo->version = entry.version; - titleInfo->installedSize = entry.size; - titleInfo->twl = false; - titleInfo->hasMeta = false; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + title_info* titleInfo = (title_info*) calloc(1, sizeof(title_info)); + if(titleInfo != NULL) { + titleInfo->mediaType = mediaType; + titleInfo->titleId = titleId; + AM_GetTitleProductCode(mediaType, titleId, titleInfo->productCode); + titleInfo->version = entry.version; + titleInfo->installedSize = entry.size; + titleInfo->twl = false; + titleInfo->hasMeta = false; - list_item* item = &data->items[*data->count]; + static const u32 filePathData[] = {0x00000000, 0x00000000, 0x00000002, 0x6E6F6369, 0x00000000}; + static const FS_Path filePath = (FS_Path) {PATH_BINARY, 0x14, (u8*) filePathData}; + u32 archivePath[] = {(u32) (titleId & 0xFFFFFFFF), (u32) ((titleId >> 32) & 0xFFFFFFFF), mediaType, 0x00000000}; + FS_Archive archive = {ARCHIVE_SAVEDATA_AND_CONTENT, (FS_Path) {PATH_BINARY, 0x10, (u8*) archivePath}}; - static const u32 filePathData[] = {0x00000000, 0x00000000, 0x00000002, 0x6E6F6369, 0x00000000}; - static const FS_Path filePath = (FS_Path) {PATH_BINARY, 0x14, (u8*) filePathData}; - u32 archivePath[] = {(u32) (titleId & 0xFFFFFFFF), (u32) ((titleId >> 32) & 0xFFFFFFFF), mediaType, 0x00000000}; - FS_Archive archive = {ARCHIVE_SAVEDATA_AND_CONTENT, (FS_Path) {PATH_BINARY, 0x10, (u8*) archivePath}}; + Handle fileHandle; + if(R_SUCCEEDED(FSUSER_OpenFileDirectly(&fileHandle, archive, filePath, FS_OPEN_READ, 0))) { + SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH)); + if(smdh != NULL) { + u32 bytesRead; + if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 0, smdh, sizeof(SMDH))) && bytesRead == sizeof(SMDH)) { + if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') { + titleInfo->hasMeta = true; - Handle fileHandle; - if(R_SUCCEEDED(FSUSER_OpenFileDirectly(&fileHandle, archive, filePath, FS_OPEN_READ, 0))) { - SMDH* smdh = (SMDH*) calloc(1, sizeof(SMDH)); - if(smdh != NULL) { - u32 bytesRead; - if(R_SUCCEEDED(FSFILE_Read(fileHandle, &bytesRead, 0, smdh, sizeof(SMDH))) && bytesRead == sizeof(SMDH)) { - if(smdh->magic[0] == 'S' && smdh->magic[1] == 'M' && smdh->magic[2] == 'D' && smdh->magic[3] == 'H') { - titleInfo->hasMeta = true; + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); - u8 systemLanguage = CFG_LANGUAGE_EN; - CFGU_GetSystemLanguage(&systemLanguage); + utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, NAME_MAX - 1); - utf16_to_utf8((uint8_t*) item->name, smdh->titles[systemLanguage].shortDescription, NAME_MAX - 1); - - utf16_to_utf8((uint8_t*) titleInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(titleInfo->meta.shortDescription) - 1); - utf16_to_utf8((uint8_t*) titleInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(titleInfo->meta.longDescription) - 1); - utf16_to_utf8((uint8_t*) titleInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(titleInfo->meta.publisher) - 1); - titleInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false); + utf16_to_utf8((uint8_t*) titleInfo->meta.shortDescription, smdh->titles[systemLanguage].shortDescription, sizeof(titleInfo->meta.shortDescription) - 1); + utf16_to_utf8((uint8_t*) titleInfo->meta.longDescription, smdh->titles[systemLanguage].longDescription, sizeof(titleInfo->meta.longDescription) - 1); + utf16_to_utf8((uint8_t*) titleInfo->meta.publisher, smdh->titles[systemLanguage].publisher, sizeof(titleInfo->meta.publisher) - 1); + titleInfo->meta.texture = screen_load_texture_tiled_auto(smdh->largeIcon, sizeof(smdh->largeIcon), 48, 48, GPU_RGB565, false); + } } + + free(smdh); } - free(smdh); + FSFILE_Close(fileHandle); } - FSFILE_Close(fileHandle); - } + bool empty = strlen(item->name) == 0; + if(!empty) { + empty = true; - bool empty = strlen(item->name) == 0; - if(!empty) { - empty = true; + char* curr = item->name; + while(*curr) { + if(*curr != ' ') { + empty = false; + break; + } - char* curr = item->name; - while(*curr) { - if(*curr != ' ') { - empty = false; - break; + curr++; } - - curr++; } + + if(empty) { + snprintf(item->name, NAME_MAX, "%016llX", titleId); + } + + if(mediaType == MEDIATYPE_NAND) { + item->color = COLOR_NAND; + } else if(mediaType == MEDIATYPE_SD) { + item->color = COLOR_SD; + } else if(mediaType == MEDIATYPE_GAME_CARD) { + item->color = COLOR_GAME_CARD; + } + + item->data = titleInfo; + + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; } - - if(empty) { - snprintf(item->name, NAME_MAX, "%016llX", titleId); - } - - if(mediaType == MEDIATYPE_NAND) { - item->rgba = COLOR_NAND; - } else if(mediaType == MEDIATYPE_SD) { - item->rgba = COLOR_SD; - } else if(mediaType == MEDIATYPE_GAME_CARD) { - item->rgba = COLOR_GAME_CARD; - } - - item->data = titleInfo; - - (*data->count)++; } else { res = R_FBI_OUT_OF_MEMORY; } @@ -139,100 +142,105 @@ static Result task_populate_titles_add_twl(populate_titles_data* data, FS_MediaT } if(R_SUCCEEDED(res)) { - title_info* titleInfo = (title_info*) calloc(1, sizeof(title_info)); - if(titleInfo != NULL) { - titleInfo->mediaType = mediaType; - titleInfo->titleId = realTitleId; - strncpy(titleInfo->productCode, productCode, 12); - titleInfo->version = version; - titleInfo->installedSize = installedSize; - titleInfo->twl = true; - titleInfo->hasMeta = false; + list_item* item = (list_item*) calloc(1, sizeof(list_item)); + if(item != NULL) { + title_info* titleInfo = (title_info*) calloc(1, sizeof(title_info)); + if(titleInfo != NULL) { + titleInfo->mediaType = mediaType; + titleInfo->titleId = realTitleId; + strncpy(titleInfo->productCode, productCode, 12); + titleInfo->version = version; + titleInfo->installedSize = installedSize; + titleInfo->twl = true; + titleInfo->hasMeta = false; - list_item* item = &data->items[*data->count]; + BNR* bnr = (BNR*) calloc(1, sizeof(BNR)); + if(bnr != NULL) { + if(R_SUCCEEDED(FSUSER_GetLegacyBannerData(mediaType, titleId, (u8*) bnr))) { + titleInfo->hasMeta = true; - BNR* bnr = (BNR*) calloc(1, sizeof(BNR)); - if(bnr != NULL) { - if(R_SUCCEEDED(FSUSER_GetLegacyBannerData(mediaType, titleId, (u8*) bnr))) { - titleInfo->hasMeta = true; + u8 systemLanguage = CFG_LANGUAGE_EN; + CFGU_GetSystemLanguage(&systemLanguage); - u8 systemLanguage = CFG_LANGUAGE_EN; - CFGU_GetSystemLanguage(&systemLanguage); + char title[0x100] = {'\0'}; + utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], sizeof(title) - 1); - char title[0x100] = {'\0'}; - utf16_to_utf8((uint8_t*) title, bnr->titles[systemLanguage], sizeof(title) - 1); + if(strchr(title, '\n') == NULL) { + size_t len = strlen(title); + strncpy(item->name, title, len); + strncpy(titleInfo->meta.shortDescription, title, len); + } else { + char* destinations[] = {titleInfo->meta.shortDescription, titleInfo->meta.longDescription, titleInfo->meta.publisher}; + int currDest = 0; - if(strchr(title, '\n') == NULL) { - size_t len = strlen(title); - strncpy(item->name, title, len); - strncpy(titleInfo->meta.shortDescription, title, len); - } else { - char* destinations[] = {titleInfo->meta.shortDescription, titleInfo->meta.longDescription, titleInfo->meta.publisher}; - int currDest = 0; + char* last = title; + char* curr = NULL; - char* last = title; - char* curr = NULL; + while(currDest < 3 && (curr = strchr(last, '\n')) != NULL) { + strncpy(destinations[currDest++], last, curr - last); + last = curr + 1; + *curr = ' '; + } - while(currDest < 3 && (curr = strchr(last, '\n')) != NULL) { - strncpy(destinations[currDest++], last, curr - last); - last = curr + 1; - *curr = ' '; + strncpy(item->name, title, last - title); + if(currDest < 3) { + strncpy(destinations[currDest], last, strlen(title) - (last - title)); + } } - strncpy(item->name, title, last - title); - if(currDest < 3) { - strncpy(destinations[currDest], last, strlen(title) - (last - title)); + u8 icon[32 * 32 * 2]; + for(u32 x = 0; x < 32; x++) { + for(u32 y = 0; y < 32; y++) { + u32 srcPos = (((y >> 3) * 4 + (x >> 3)) * 8 + (y & 7)) * 4 + ((x & 7) >> 1); + u32 srcShift = (x & 1) * 4; + u16 srcPx = bnr->mainIconPalette[(bnr->mainIconBitmap[srcPos] >> srcShift) & 0xF]; + + u8 r = (u8) (srcPx & 0x1F); + u8 g = (u8) ((srcPx >> 5) & 0x1F); + u8 b = (u8) ((srcPx >> 10) & 0x1F); + + u16 reversedPx = (u16) ((r << 11) | (g << 6) | (b << 1) | 1); + + u32 dstPos = (y * 32 + x) * 2; + icon[dstPos + 0] = (u8) (reversedPx & 0xFF); + icon[dstPos + 1] = (u8) ((reversedPx >> 8) & 0xFF); + } } + + titleInfo->meta.texture = screen_load_texture_auto(icon, sizeof(icon), 32, 32, GPU_RGBA5551, false); } - u8 icon[32 * 32 * 2]; - for(u32 x = 0; x < 32; x++) { - for(u32 y = 0; y < 32; y++) { - u32 srcPos = (((y >> 3) * 4 + (x >> 3)) * 8 + (y & 7)) * 4 + ((x & 7) >> 1); - u32 srcShift = (x & 1) * 4; - u16 srcPx = bnr->mainIconPalette[(bnr->mainIconBitmap[srcPos] >> srcShift) & 0xF]; - - u8 r = (u8) (srcPx & 0x1F); - u8 g = (u8) ((srcPx >> 5) & 0x1F); - u8 b = (u8) ((srcPx >> 10) & 0x1F); - - u16 reversedPx = (u16) ((r << 11) | (g << 6) | (b << 1) | 1); - - u32 dstPos = (y * 32 + x) * 2; - icon[dstPos + 0] = (u8) (reversedPx & 0xFF); - icon[dstPos + 1] = (u8) ((reversedPx >> 8) & 0xFF); - } - } - - titleInfo->meta.texture = screen_load_texture_auto(icon, sizeof(icon), 32, 32, GPU_RGBA5551, false); + free(bnr); } - free(bnr); - } + bool empty = strlen(item->name) == 0; + if(!empty) { + empty = true; - bool empty = strlen(item->name) == 0; - if(!empty) { - empty = true; + char* curr = item->name; + while(*curr) { + if(*curr != ' ') { + empty = false; + break; + } - char* curr = item->name; - while(*curr) { - if(*curr != ' ') { - empty = false; - break; + curr++; } - - curr++; } + + if(empty) { + snprintf(item->name, NAME_MAX, "%016llX", realTitleId); + } + + item->color = COLOR_DS_TITLE; + item->data = titleInfo; + + linked_list_add(data->items, item); + } else { + free(item); + + res = R_FBI_OUT_OF_MEMORY; } - - if(empty) { - snprintf(item->name, NAME_MAX, "%016llX", realTitleId); - } - - item->rgba = COLOR_DS_TITLE; - item->data = titleInfo; - - (*data->count)++; } else { res = R_FBI_OUT_OF_MEMORY; } @@ -258,7 +266,7 @@ static Result task_populate_titles_from(populate_titles_data* data, FS_MediaType if(R_SUCCEEDED(res = AM_GetTitleList(&titleCount, mediaType, titleCount, titleIds))) { qsort(titleIds, titleCount, sizeof(u64), util_compare_u64); - for(u32 i = 0; i < titleCount && *data->count < data->max && R_SUCCEEDED(res); i++) { + for(u32 i = 0; i < titleCount && R_SUCCEEDED(res); i++) { if(task_is_quit_all() || svcWaitSynchronization(data->cancelEvent, 0) == 0) { break; } @@ -296,36 +304,38 @@ static void task_populate_titles_thread(void* arg) { free(data); } -void task_clear_titles(list_item* items, u32* count) { - if(items == NULL || count == NULL) { +void task_clear_titles(linked_list* items) { + if(items == NULL) { return; } - u32 prevCount = *count; - *count = 0; + linked_list_iter iter; + linked_list_iterate(items, &iter); - for(u32 i = 0; i < prevCount; i++) { - if(items[i].data != NULL) { - title_info* titleInfo = (title_info*) items[i].data; + while(linked_list_iter_has_next(&iter)) { + list_item* item = (list_item*) linked_list_iter_next(&iter); + + if(item->data != NULL) { + title_info* titleInfo = (title_info*) item->data; if(titleInfo->hasMeta) { screen_unload_texture(titleInfo->meta.texture); } - free(items[i].data); - items[i].data = NULL; + free(item->data); } - memset(items[i].name, '\0', NAME_MAX); - items[i].rgba = 0; + free(item); + + linked_list_iter_remove(&iter); } } -Handle task_populate_titles(list_item* items, u32* count, u32 max) { - if(items == NULL || count == NULL || max == 0) { +Handle task_populate_titles(linked_list* items) { + if(items == NULL) { return 0; } - task_clear_titles(items, count); + task_clear_titles(items); populate_titles_data* data = (populate_titles_data*) calloc(1, sizeof(populate_titles_data)); if(data == NULL) { @@ -335,8 +345,6 @@ Handle task_populate_titles(list_item* items, u32* count, u32 max) { } data->items = items; - data->count = count; - data->max = max; Result eventRes = svcCreateEvent(&data->cancelEvent, 1); if(R_FAILED(eventRes)) { diff --git a/source/ui/section/task/task.h b/source/ui/section/task/task.h index ea670d0..28380a9 100644 --- a/source/ui/section/task/task.h +++ b/source/ui/section/task/task.h @@ -2,7 +2,14 @@ #include -#include "../../list.h" +#include "../../../core/linkedlist.h" + +#define R_FBI_CANCELLED MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, 1) +#define R_FBI_ERRNO MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 2) +#define R_FBI_HTTP_RESPONSE_CODE MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 3) +#define R_FBI_WRONG_SYSTEM MAKERESULT(RL_PERMANENT, RS_NOTSUPPORTED, RM_APPLICATION, 4) + +#define R_FBI_OUT_OF_MEMORY MAKERESULT(RL_FATAL, RS_OUTOFRESOURCE, RM_APPLICATION, RD_OUT_OF_MEMORY) typedef struct { char shortDescription[0x100]; @@ -68,13 +75,6 @@ typedef struct { ticket_info ticketInfo; } file_info; -#define R_FBI_CANCELLED MAKERESULT(RL_PERMANENT, RS_CANCELED, RM_APPLICATION, 1) -#define R_FBI_ERRNO MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 2) -#define R_FBI_HTTP_RESPONSE_CODE MAKERESULT(RL_PERMANENT, RS_INTERNAL, RM_APPLICATION, 3) -#define R_FBI_WRONG_SYSTEM MAKERESULT(RL_PERMANENT, RS_NOTSUPPORTED, RM_APPLICATION, 4) - -#define R_FBI_OUT_OF_MEMORY MAKERESULT(RL_FATAL, RS_OUTOFRESOURCE, RM_APPLICATION, RD_OUT_OF_MEMORY) - typedef enum { DATAOP_COPY, DATAOP_DELETE @@ -125,20 +125,20 @@ Handle task_capture_cam(Handle* mutex, u16* buffer, s16 width, s16 height); Handle task_data_op(data_op_info* info); -void task_clear_ext_save_data(list_item* items, u32* count); -Handle task_populate_ext_save_data(list_item* items, u32* count, u32 max); +void task_clear_ext_save_data(linked_list* items); +Handle task_populate_ext_save_data(linked_list* items); -void task_clear_files(list_item* items, u32* count); -Handle task_populate_files(list_item* items, u32* count, u32 max, file_info* dir); +void task_clear_files(linked_list* items); +Handle task_populate_files(linked_list* items, file_info* dir); -void task_clear_pending_titles(list_item* items, u32* count); -Handle task_populate_pending_titles(list_item* items, u32* count, u32 max); +void task_clear_pending_titles(linked_list* items); +Handle task_populate_pending_titles(linked_list* items); -void task_clear_system_save_data(list_item* items, u32* count); -Handle task_populate_system_save_data(list_item* items, u32* count, u32 max); +void task_clear_system_save_data(linked_list* items); +Handle task_populate_system_save_data(linked_list* items); -void task_clear_tickets(list_item* items, u32* count); -Handle task_populate_tickets(list_item* items, u32* count, u32 max); +void task_clear_tickets(linked_list* items); +Handle task_populate_tickets(linked_list* items); -void task_clear_titles(list_item* items, u32* count); -Handle task_populate_titles(list_item* items, u32* count, u32 max); \ No newline at end of file +void task_clear_titles(linked_list* items); +Handle task_populate_titles(linked_list* items); \ No newline at end of file diff --git a/source/ui/section/tickets.c b/source/ui/section/tickets.c index 754af4f..a895827 100644 --- a/source/ui/section/tickets.c +++ b/source/ui/section/tickets.c @@ -6,25 +6,17 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" -#define TICKETS_MAX 1024 +static list_item install_from_cdn = {"Install from CDN", COLOR_TEXT, action_install_cdn}; +static list_item delete_ticket = {"Delete Ticket", COLOR_TEXT, action_delete_ticket}; typedef struct { - list_item items[TICKETS_MAX]; - u32 count; Handle cancelEvent; bool populated; } tickets_data; -#define TICKETS_ACTION_COUNT 2 - -static u32 tickets_action_count = TICKETS_ACTION_COUNT; -static list_item tickets_action_items[TICKETS_ACTION_COUNT] = { - {"Install from CDN", COLOR_TEXT, action_install_cdn}, - {"Delete Ticket", COLOR_TEXT, action_delete_ticket}, -}; - typedef struct { ticket_info* info; bool* populated; @@ -34,7 +26,7 @@ static void tickets_action_draw_top(ui_view* view, void* data, float x1, float y ui_draw_ticket_info(view, ((tickets_action_data*) data)->info, x1, y1, x2, y2); } -static void tickets_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void tickets_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { tickets_action_data* actionData = (tickets_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -59,9 +51,9 @@ static void tickets_action_update(ui_view* view, void* data, list_item** items, return; } - if(*itemCount != &tickets_action_count || *items != tickets_action_items) { - *itemCount = &tickets_action_count; - *items = tickets_action_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &install_from_cdn); + linked_list_add(items, &delete_ticket); } } @@ -85,7 +77,7 @@ static void tickets_draw_top(ui_view* view, void* data, float x1, float y1, floa } } -static void tickets_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void tickets_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { tickets_data* listData = (tickets_data*) data; if(hidKeysDown() & KEY_B) { @@ -99,9 +91,10 @@ static void tickets_update(ui_view* view, void* data, list_item** items, u32** i } ui_pop(); + + task_clear_tickets(items); list_destroy(view); - task_clear_tickets(listData->items, &listData->count); free(listData); return; } @@ -116,7 +109,7 @@ static void tickets_update(ui_view* view, void* data, list_item** items, u32** i listData->cancelEvent = 0; } - listData->cancelEvent = task_populate_tickets(listData->items, &listData->count, TICKETS_MAX); + listData->cancelEvent = task_populate_tickets(items); listData->populated = true; } @@ -124,11 +117,6 @@ static void tickets_update(ui_view* view, void* data, list_item** items, u32** i tickets_action_open((ticket_info*) selected->data, &listData->populated); return; } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; - } } void tickets_open() { diff --git a/source/ui/section/titles.c b/source/ui/section/titles.c index d362f8c..a88945f 100644 --- a/source/ui/section/titles.c +++ b/source/ui/section/titles.c @@ -6,52 +6,22 @@ #include "action/action.h" #include "section.h" #include "../error.h" +#include "../list.h" #include "../../screen.h" +#include "task/task.h" -#define TITLES_MAX 1024 +static list_item launch_title = {"Launch Title", COLOR_TEXT, action_launch_title}; +static list_item delete_title = {"Delete Title", COLOR_TEXT, action_delete_title}; +static list_item browse_save_data = {"Browse Save Data", COLOR_TEXT, action_browse_title_save_data}; +static list_item import_secure_value = {"Import Secure Value", COLOR_TEXT, action_import_secure_value}; +static list_item export_secure_value = {"Export Secure Value", COLOR_TEXT, action_export_secure_value}; +static list_item delete_secure_value = {"Delete Secure Value", COLOR_TEXT, action_delete_secure_value}; typedef struct { - list_item items[TITLES_MAX]; - u32 count; Handle cancelEvent; bool populated; } titles_data; -#define TITLES_ACTION_COUNT 6 - -static u32 titles_action_count = TITLES_ACTION_COUNT; -static list_item titles_action_items[TITLES_ACTION_COUNT] = { - {"Launch Title", COLOR_TEXT, action_launch_title}, - {"Delete Title", COLOR_TEXT, action_delete_title}, - {"Browse Save Data", COLOR_TEXT, action_browse_title_save_data}, - {"Import Secure Value", COLOR_TEXT, action_import_secure_value}, - {"Export Secure Value", COLOR_TEXT, action_export_secure_value}, - {"Delete Secure Value", COLOR_TEXT, action_delete_secure_value}, -}; - -#define CARD_TITLES_ACTION_COUNT 2 - -static u32 card_titles_action_count = CARD_TITLES_ACTION_COUNT; -static list_item card_titles_action_items[CARD_TITLES_ACTION_COUNT] = { - {"Launch Title", COLOR_TEXT, action_launch_title}, - {"Browse Save Data", COLOR_TEXT, action_browse_title_save_data}, -}; - -#define DSIWARE_TITLES_ACTION_COUNT 2 - -static u32 dsiware_titles_action_count = DSIWARE_TITLES_ACTION_COUNT; -static list_item dsiware_titles_action_items[DSIWARE_TITLES_ACTION_COUNT] = { - {"Launch Title", COLOR_TEXT, action_launch_title}, - {"Delete Title", COLOR_TEXT, action_delete_title}, -}; - -#define DSIWARE_CARD_TITLES_ACTION_COUNT 1 - -static u32 dsiware_card_titles_action_count = DSIWARE_CARD_TITLES_ACTION_COUNT; -static list_item dsiware_card_titles_action_items[DSIWARE_CARD_TITLES_ACTION_COUNT] = { - {"Launch Title", COLOR_TEXT, action_launch_title}, -}; - typedef struct { title_info* info; bool* populated; @@ -61,7 +31,7 @@ static void titles_action_draw_top(ui_view* view, void* data, float x1, float y1 ui_draw_title_info(view, ((titles_action_data*) data)->info, x1, y1, x2, y2); } -static void titles_action_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void titles_action_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { titles_action_data* actionData = (titles_action_data*) data; if(hidKeysDown() & KEY_B) { @@ -86,25 +56,21 @@ static void titles_action_update(ui_view* view, void* data, list_item** items, u return; } - if(actionData->info->mediaType == MEDIATYPE_GAME_CARD && actionData->info->twl) { - if(*itemCount != &dsiware_card_titles_action_count || *items != dsiware_card_titles_action_items) { - *itemCount = &dsiware_card_titles_action_count; - *items = dsiware_card_titles_action_items; + if(linked_list_size(items) == 0) { + linked_list_add(items, &launch_title); + + if(actionData->info->mediaType != MEDIATYPE_GAME_CARD) { + linked_list_add(items, &delete_title); } - } else if(actionData->info->mediaType == MEDIATYPE_GAME_CARD) { - if(*itemCount != &card_titles_action_count || *items != card_titles_action_items) { - *itemCount = &card_titles_action_count; - *items = card_titles_action_items; - } - } else if(actionData->info->twl) { - if(*itemCount != &dsiware_titles_action_count || *items != dsiware_titles_action_items) { - *itemCount = &dsiware_titles_action_count; - *items = dsiware_titles_action_items; - } - } else { - if(*itemCount != &titles_action_count || *items != titles_action_items) { - *itemCount = &titles_action_count; - *items = titles_action_items; + + if(!actionData->info->twl) { + linked_list_add(items, &browse_save_data); + + if(actionData->info->mediaType != MEDIATYPE_GAME_CARD) { + linked_list_add(items, &import_secure_value); + linked_list_add(items, &export_secure_value); + linked_list_add(items, &delete_secure_value); + } } } } @@ -129,7 +95,7 @@ static void titles_draw_top(ui_view* view, void* data, float x1, float y1, float } } -static void titles_update(ui_view* view, void* data, list_item** items, u32** itemCount, list_item* selected, bool selectedTouched) { +static void titles_update(ui_view* view, void* data, linked_list* items, list_item* selected, bool selectedTouched) { titles_data* listData = (titles_data*) data; if(hidKeysDown() & KEY_B) { @@ -143,9 +109,10 @@ static void titles_update(ui_view* view, void* data, list_item** items, u32** it } ui_pop(); + + task_clear_titles(items); list_destroy(view); - task_clear_titles(listData->items, &listData->count); free(listData); return; } @@ -160,7 +127,7 @@ static void titles_update(ui_view* view, void* data, list_item** items, u32** it listData->cancelEvent = 0; } - listData->cancelEvent = task_populate_titles(listData->items, &listData->count, TITLES_MAX); + listData->cancelEvent = task_populate_titles(items); listData->populated = true; } @@ -168,11 +135,6 @@ static void titles_update(ui_view* view, void* data, list_item** items, u32** it titles_action_open((title_info*) selected->data, &listData->populated); return; } - - if(*itemCount != &listData->count || *items != listData->items) { - *itemCount = &listData->count; - *items = listData->items; - } } void titles_open() {