diff --git a/include/loading.h b/include/loading.h index e50dd4f..40df206 100644 --- a/include/loading.h +++ b/include/loading.h @@ -70,7 +70,6 @@ typedef struct { ssize_t texture_id_offset; ssize_t icons_ids[ICONS_OFFSET_AMOUNT][ENTRIES_PER_SCREEN]; - ssize_t assoc_entry_ids[ICONS_OFFSET_AMOUNT][ENTRIES_PER_SCREEN]; int previous_scroll; int scroll; @@ -92,6 +91,7 @@ void delete_entry(Entry_s entry); Result load_entries(const char * loading_path, Entry_List_s * list, EntryMode mode); bool load_preview(Entry_List_s list, int * preview_offset); void load_icons_first(Entry_List_s * current_list, bool silent); +void handle_scrolling(Entry_List_s * list); void load_icons_thread(void * void_arg); u32 load_data(char * filename, Entry_s entry, char ** buf); diff --git a/source/loading.c b/source/loading.c index f8d2db8..3486b55 100644 --- a/source/loading.c +++ b/source/loading.c @@ -167,89 +167,45 @@ Result load_entries(const char * loading_path, Entry_List_s * list, EntryMode mo return res; } -static void small_load(Entry_List_s * current_list) +void load_icons_first(Entry_List_s * list, bool silent) { - DEBUG("small load\n"); - - ssize_t * icons_ids = (ssize_t *)current_list->icons_ids; - ssize_t * assoc_entry_ids = (ssize_t *)current_list->assoc_entry_ids; - ssize_t id = current_list->texture_id_offset; - for(int i = 0; i < current_list->entries_count; i++, id++) - { - Entry_s current_entry = current_list->entries[i]; - load_smdh_icon(current_entry, id); - icons_ids[i] = id; - assoc_entry_ids[i] = i; - } -} - -static void first_load(Entry_List_s * current_list) -{ - DEBUG("first load\n"); - - ssize_t * above_icons_ids = current_list->icons_ids[ICONS_ABOVE]; - ssize_t * visible_icons_ids = current_list->icons_ids[ICONS_VISIBLE]; - ssize_t * under_icons_ids = current_list->icons_ids[ICONS_UNDER]; - - ssize_t * above_assoc_ids = current_list->assoc_entry_ids[ICONS_ABOVE]; - ssize_t * visible_assoc_ids = current_list->assoc_entry_ids[ICONS_VISIBLE]; - ssize_t * under_assoc_ids = current_list->assoc_entry_ids[ICONS_UNDER]; - - ssize_t id = current_list->texture_id_offset; - int starti = current_list->scroll; - - memset(visible_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t)); - for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++) - { - if(i >= current_list->entries_count) break; - - Entry_s current_entry = current_list->entries[i]; - load_smdh_icon(current_entry, id); - visible_icons_ids[i-starti] = id; - visible_assoc_ids[i-starti] = i; - } - - memset(above_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t)); - starti -= ENTRIES_PER_SCREEN; - for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++) - { - if(i >= current_list->entries_count) break; - int used_i = i; - if(i < 0) - used_i = current_list->entries_count + i; - - Entry_s current_entry = current_list->entries[used_i]; - load_smdh_icon(current_entry, id); - above_icons_ids[i-starti] = id; - above_assoc_ids[i-starti] = used_i; - } - - memset(under_icons_ids, 0, ENTRIES_PER_SCREEN*sizeof(ssize_t)); - starti += ENTRIES_PER_SCREEN*2; - for(int i = starti; i < starti+ENTRIES_PER_SCREEN; i++, id++) - { - int used_i = i; - if(i >= current_list->entries_count) - used_i = i - current_list->entries_count; - - Entry_s current_entry = current_list->entries[used_i]; - load_smdh_icon(current_entry, id); - under_icons_ids[i-starti] = id; - under_assoc_ids[i-starti] = used_i; - } -} - -void load_icons_first(Entry_List_s * current_list, bool silent) -{ - if(current_list == NULL || current_list->entries == NULL) return; + if(list == NULL || list->entries == NULL) return; if(!silent) draw_install(INSTALL_LOADING_ICONS); - if(current_list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT) - small_load(current_list); // if the list is one that doesnt need swapping, load everything at once + int starti = 0, endi = 0; + + if(list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT) + { + DEBUG("small load\n"); + // if the list is one that doesnt need swapping, load everything at once + endi = list->entries_count; + } else - first_load(current_list); + { + DEBUG("extended load\n"); + // otherwise, load around to prepare for swapping + starti = list->scroll - ENTRIES_PER_SCREEN*ICONS_VISIBLE; + endi = starti + ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT; + } + + ssize_t * icon_ids = (ssize_t *)list->icons_ids; + ssize_t id = list->texture_id_offset; + + memset(icon_ids, 0, ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT*sizeof(ssize_t)); + for(int i = starti; i < endi; i++, id++) + { + int offset = i; + if(offset < 0) + offset += list->entries_count; + if(offset >= list->entries_count) + offset -= list->entries_count; + + Entry_s current_entry = list->entries[offset]; + load_smdh_icon(current_entry, id); + icon_ids[i-starti] = id; + } } static void reverse(ssize_t a[], int sz) { @@ -269,18 +225,71 @@ static void rotate(ssize_t array[], int size, int amt) { reverse(array, size-1); } +void handle_scrolling(Entry_List_s * list) +{ + // Scroll the menu up or down if the selected theme is out of its bounds + //---------------------------------------------------------------- + if(list->entries_count > ENTRIES_PER_SCREEN) + { + for(int i = 0; i < list->entries_count; i++) + { + int change = 0; + + if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->previous_scroll < ENTRIES_PER_SCREEN && list->selected_entry >= list->entries_count - ENTRIES_PER_SCREEN) + { + list->scroll = list->entries_count - ENTRIES_PER_SCREEN; + } + else if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->selected_entry < ENTRIES_PER_SCREEN && list->previous_selected >= list->entries_count - ENTRIES_PER_SCREEN) + { + list->scroll = 0; + } + else if(list->selected_entry == list->previous_selected+1 && list->selected_entry == list->scroll+ENTRIES_PER_SCREEN) + { + change = 1; + } + else if(list->selected_entry == list->previous_selected-1 && list->selected_entry == list->scroll-1) + { + change = -1; + } + else if(list->selected_entry == list->previous_selected+ENTRIES_PER_SCREEN || list->selected_entry >= list->scroll + ENTRIES_PER_SCREEN) + { + change = ENTRIES_PER_SCREEN; + } + else if(list->selected_entry == list->previous_selected-ENTRIES_PER_SCREEN || list->selected_entry < list->scroll) + { + change = -ENTRIES_PER_SCREEN; + } + + list->scroll += change; + + if(list->scroll < 0) + list->scroll = 0; + else if(list->scroll > list->entries_count - ENTRIES_PER_SCREEN) + list->scroll = list->entries_count - ENTRIES_PER_SCREEN; + + if(!change) + list->previous_selected = list->selected_entry; + else + list->previous_selected += change; + } + } + //---------------------------------------------------------------- +} + static void load_icons(Entry_List_s * current_list) { if(current_list == NULL || current_list->entries == NULL) return; + handle_scrolling(current_list); + if(current_list->entries_count <= ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT || current_list->previous_scroll == current_list->scroll) return; // return if the list is one that doesnt need swapping, or if nothing changed #define SIGN(x) (x > 0 ? 1 : ((x < 0) ? -1 : 0)) int delta = current_list->scroll - current_list->previous_scroll; - if(abs(delta) >= current_list->entries_count - ENTRIES_PER_SCREEN*2) + if(abs(delta) >= current_list->entries_count - ENTRIES_PER_SCREEN*(ICONS_OFFSET_AMOUNT-1)) delta = -SIGN(delta) * (current_list->entries_count - abs(delta)); int starti = current_list->scroll; @@ -300,27 +309,23 @@ static void load_icons(Entry_List_s * current_list) #define LAST(arr) arr[ENTRIES_PER_SCREEN*ICONS_OFFSET_AMOUNT - 1] ssize_t * icons_ids = (ssize_t *)current_list->icons_ids; - ssize_t * assoc_entry_ids = (ssize_t *)current_list->assoc_entry_ids; for(int i = starti; i != endi; i++, ctr++) { ssize_t id = 0; int offset = i; - ssize_t * assoc = NULL; - rotate(icons_ids, 3*ENTRIES_PER_SCREEN, -1*SIGN(delta)); + rotate(icons_ids, ICONS_OFFSET_AMOUNT*ENTRIES_PER_SCREEN, -1*SIGN(delta)); if(delta > 0) { id = LAST(icons_ids); - assoc = &LAST(assoc_entry_ids); - offset += ENTRIES_PER_SCREEN*2 - delta; + offset += ENTRIES_PER_SCREEN*ICONS_UNDER - delta; } else { id = FIRST(icons_ids); - assoc = &FIRST(assoc_entry_ids); - offset -= ENTRIES_PER_SCREEN; + offset -= ENTRIES_PER_SCREEN*ICONS_VISIBLE; i -= 2; //i-- twice to counter the i++, needed only for this case } @@ -331,7 +336,6 @@ static void load_icons(Entry_List_s * current_list) entries[ctr] = ¤t_list->entries[offset]; ids[ctr] = id; - *assoc = id; } #undef FIRST @@ -341,9 +345,13 @@ static void load_icons(Entry_List_s * current_list) svcSleepThread(1e6); for(int i = 0; i < abs(delta); i++) load_smdh_icon(*entries[i], ids[i]); + + free(entries); + free(ids); + + current_list->previous_scroll = current_list->scroll; } -static bool loading_icons = false; void load_icons_thread(void * void_arg) { Thread_Arg_s * arg = (Thread_Arg_s *)void_arg; @@ -352,11 +360,8 @@ void load_icons_thread(void * void_arg) { svcWaitSynchronization(update_request, U64_MAX); svcClearEvent(update_request); - if(loading_icons) continue; - loading_icons = true; volatile Entry_List_s * current_list = *(volatile Entry_List_s **)arg->thread_arg[0]; load_icons((Entry_List_s *)current_list); - loading_icons = false; } while(arg->run_thread); } diff --git a/source/main.c b/source/main.c index 99ad475..455b161 100644 --- a/source/main.c +++ b/source/main.c @@ -34,7 +34,7 @@ #include "pp2d/pp2d/pp2d.h" #include -#define FASTSCROLL_WAIT 1e8 +#define FASTSCROLL_WAIT 1.5e8 static bool homebrew = false; static bool installed_themes = false; @@ -88,7 +88,6 @@ static void stop_install_check(void) if(installCheckThreads_arg[i].run_thread) { installCheckThreads_arg[i].run_thread = false; - threadJoin(installCheckThreads[i], U64_MAX); } } } @@ -183,45 +182,6 @@ static void jump_menu(Entry_List_s * list) } } -static void handle_scrolling(Entry_List_s * list) -{ - // Scroll the menu up or down if the selected theme is out of its bounds - //---------------------------------------------------------------- - if(list->entries_count > ENTRIES_PER_SCREEN) - { - if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->previous_scroll < ENTRIES_PER_SCREEN && list->selected_entry >= list->entries_count - ENTRIES_PER_SCREEN) - { - list->scroll = list->entries_count - ENTRIES_PER_SCREEN; - } - else if(list->entries_count > ENTRIES_PER_SCREEN*2 && list->selected_entry < ENTRIES_PER_SCREEN && list->previous_selected >= list->entries_count - ENTRIES_PER_SCREEN) - { - list->scroll = 0; - } - else if(list->selected_entry == list->previous_selected+1 && list->selected_entry == list->scroll+ENTRIES_PER_SCREEN) - { - list->scroll++; - } - else if(list->selected_entry == list->previous_selected-1 && list->selected_entry == list->scroll-1) - { - list->scroll--; - } - else if(list->selected_entry == list->previous_selected+ENTRIES_PER_SCREEN || list->selected_entry >= list->scroll + ENTRIES_PER_SCREEN) - { - list->scroll += ENTRIES_PER_SCREEN; - } - else if(list->selected_entry == list->previous_selected-ENTRIES_PER_SCREEN || list->selected_entry < list->scroll) - { - list->scroll -= ENTRIES_PER_SCREEN; - } - - if(list->scroll < 0) - list->scroll = 0; - if(list->scroll > list->entries_count - ENTRIES_PER_SCREEN) - list->scroll = list->entries_count - ENTRIES_PER_SCREEN; - } - //---------------------------------------------------------------- -} - static void change_selected(Entry_List_s * list, int change_value) { if(abs(change_value) >= list->entries_count) return; @@ -348,12 +308,16 @@ int main(void) if(qr_mode) take_picture(); else if(preview_mode) draw_preview(preview_offset); else { - handle_scrolling(current_list); - svcSignalEvent(update_icons_handle); - svcSleepThread(1e6); - - current_list->previous_scroll = current_list->scroll; - current_list->previous_selected = current_list->selected_entry; + if(!iconLoadingThread_arg.run_thread) + { + handle_scrolling(current_list); + current_list->previous_scroll = current_list->scroll; + } + else + { + svcSignalEvent(update_icons_handle); + svcSleepThread(5e6); + } draw_interface(current_list, instructions); svcSleepThread(1e7); @@ -606,12 +570,10 @@ int main(void) else if(kDown & KEY_LEFT) { change_selected(current_list, -ENTRIES_PER_SCREEN); - load_icons_first(current_list, true); } else if(kDown & KEY_RIGHT) { change_selected(current_list, ENTRIES_PER_SCREEN); - load_icons_first(current_list, true); } // Fast scroll using circle pad @@ -657,7 +619,6 @@ int main(void) if(BETWEEN(arrowStartX, x, arrowEndX) && current_list->scroll > 0) { change_selected(current_list, -ENTRIES_PER_SCREEN); - load_icons_first(current_list, true); } else if(BETWEEN(320-24, x, 320)) { @@ -685,7 +646,6 @@ int main(void) if(BETWEEN(arrowStartX, x, arrowEndX) && current_list->scroll < current_list->entries_count - ENTRIES_PER_SCREEN) { change_selected(current_list, ENTRIES_PER_SCREEN); - load_icons_first(current_list, true); } else if(BETWEEN(176, x, 320)) {