diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 2a06e348c..7f1383ae5 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -13,6 +13,7 @@ #include #include #include +#include #define TAG "FapLoader" @@ -243,6 +244,9 @@ static void fap_loader_free(FapLoader* loader) { } int32_t fap_loader_app(char* p) { + size_t start = furi_get_tick(); + XTREME_ASSETS_FREE(); + FURI_LOG_I("Assets", "Freed in %ums", (size_t)(furi_get_tick() - start)); FapLoader* loader; process_favorite_launch(&p); if(p) { @@ -262,5 +266,9 @@ int32_t fap_loader_app(char* p) { } fap_loader_free(loader); + + start = furi_get_tick(); + XTREME_ASSETS_LOAD(); + FURI_LOG_I("Assets", "Loaded in %ums", (size_t)(furi_get_tick() - start)); return 0; } diff --git a/applications/services/gui/icon_i.h b/applications/services/gui/icon_i.h index 58cac8b41..1fa6d523f 100644 --- a/applications/services/gui/icon_i.h +++ b/applications/services/gui/icon_i.h @@ -12,4 +12,5 @@ struct Icon { const uint8_t frame_count; const uint8_t frame_rate; const uint8_t* const* frames; + Icon* original; }; diff --git a/lib/xtreme/assets.c b/lib/xtreme/assets.c index 4f01eb358..e291d6074 100644 --- a/lib/xtreme/assets.c +++ b/lib/xtreme/assets.c @@ -9,7 +9,7 @@ #define ICONS_FMT XTREME_ASSETS_PATH "/%s/Icons/%s" -void swap_icon_animated(const Icon* replace, const char* name, FuriString* path, File* file) { +void load_icon_animated(const Icon* replace, const char* name, FuriString* path, File* file) { const char* pack = XTREME_SETTINGS()->asset_pack; furi_string_printf(path, ICONS_FMT "/meta", pack, name); if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { @@ -41,10 +41,13 @@ void swap_icon_animated(const Icon* replace, const char* name, FuriString* path, } if(i == frame_count) { - FURI_CONST_ASSIGN(replace->frame_count, frame_count); - FURI_CONST_ASSIGN(replace->frame_rate, frame_rate); + Icon* original = malloc(sizeof(Icon)); + memcpy(original, replace, sizeof(Icon)); + FURI_CONST_ASSIGN_PTR(replace->original, original); FURI_CONST_ASSIGN(replace->width, icon_width); FURI_CONST_ASSIGN(replace->height, icon_height); + FURI_CONST_ASSIGN(replace->frame_rate, frame_rate); + FURI_CONST_ASSIGN(replace->frame_count, frame_count); FURI_CONST_ASSIGN_PTR(replace->frames, frames); } else { for(; i >= 0; i--) { @@ -57,7 +60,7 @@ void swap_icon_animated(const Icon* replace, const char* name, FuriString* path, storage_file_close(file); } -void swap_icon_static(const Icon* replace, const char* name, FuriString* path, File* file) { +void load_icon_static(const Icon* replace, const char* name, FuriString* path, File* file) { furi_string_printf(path, ICONS_FMT ".bmx", XTREME_SETTINGS()->asset_pack, name); if(storage_file_open(file, furi_string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { uint64_t size = storage_file_size(file) - 8; @@ -67,12 +70,16 @@ void swap_icon_static(const Icon* replace, const char* name, FuriString* path, F if(storage_file_read(file, &icon_width, 4) == 4 && storage_file_read(file, &icon_height, 4) == 4 && storage_file_read(file, frame, size) == size) { - FURI_CONST_ASSIGN(replace->frame_count, 1); + Icon* original = malloc(sizeof(Icon)); + memcpy(original, replace, sizeof(Icon)); + FURI_CONST_ASSIGN_PTR(replace->original, original); + uint8_t** frames = malloc(sizeof(const uint8_t*)); + frames[0] = frame; FURI_CONST_ASSIGN(replace->frame_rate, 0); + FURI_CONST_ASSIGN(replace->frame_count, 1); FURI_CONST_ASSIGN(replace->width, icon_width); FURI_CONST_ASSIGN(replace->height, icon_height); - FURI_CONST_ASSIGN_PTR(replace->frames, malloc(sizeof(const uint8_t*))); - FURI_CONST_ASSIGN_PTR(replace->frames[0], frame); + FURI_CONST_ASSIGN_PTR(replace->frames, frames); } else { free(frame); } @@ -80,6 +87,20 @@ void swap_icon_static(const Icon* replace, const char* name, FuriString* path, F storage_file_close(file); } +void free_icon(const Icon* icon) { + uint8_t** frames = (void*)icon->frames; + int32_t frame_count = icon->frame_count; + + Icon* original = icon->original; + memcpy((void*)icon, original, sizeof(Icon)); + + free(original); + for(int32_t i = 0; i < frame_count; i++) { + free(frames[i]); + } + free(frames); +} + void XTREME_ASSETS_LOAD() { if(!furi_hal_is_normal_boot()) return; @@ -95,10 +116,12 @@ void XTREME_ASSETS_LOAD() { File* f = storage_file_alloc(storage); for(size_t i = 0; i < ICON_PATHS_COUNT; i++) { - if(ICON_PATHS[i].animated) { - swap_icon_animated(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f); - } else { - swap_icon_static(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f); + if(ICON_PATHS[i].icon->original == NULL) { + if(ICON_PATHS[i].animated) { + load_icon_animated(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f); + } else { + load_icon_static(ICON_PATHS[i].icon, ICON_PATHS[i].path, p, f); + } } } @@ -107,3 +130,13 @@ void XTREME_ASSETS_LOAD() { furi_string_free(p); furi_record_close(RECORD_STORAGE); } + +void XTREME_ASSETS_FREE() { + if(!furi_hal_is_normal_boot()) return; + + for(size_t i = 0; i < ICON_PATHS_COUNT; i++) { + if(ICON_PATHS[i].icon->original != NULL) { + free_icon(ICON_PATHS[i].icon); + } + } +} diff --git a/lib/xtreme/private.h b/lib/xtreme/private.h index 2718b67af..4bed4e4e7 100644 --- a/lib/xtreme/private.h +++ b/lib/xtreme/private.h @@ -3,3 +3,4 @@ void NAMESPOOF_INIT(); void XTREME_SETTINGS_LOAD(); void XTREME_ASSETS_LOAD(); +void XTREME_ASSETS_FREE();