diff --git a/src/menu/png_decoder.c b/src/menu/png_decoder.c index 1a0d8441e..da13eb591 100644 --- a/src/menu/png_decoder.c +++ b/src/menu/png_decoder.c @@ -173,7 +173,10 @@ png_err_t png_decoder_start_mem (void *buf, size_t buf_size, int max_width, int if (decoder != NULL) return PNG_ERR_BUSY; decoder = calloc(1, sizeof(png_decoder_t)); - if (decoder == NULL) return PNG_ERR_OUT_OF_MEM; + if (decoder == NULL) { + free(buf); + return PNG_ERR_OUT_OF_MEM; + } decoder->callback = callback; decoder->callback_data = callback_data; @@ -252,8 +255,12 @@ void png_decoder_poll (void) { } if (err == SPNG_EOI) { - decoder->callback(PNG_OK, decoder->image, decoder->callback_data); + png_callback_t *callback = decoder->callback; + void *callback_data = decoder->callback_data; + surface_t *image = decoder->image; + decoder->image = NULL; png_decoder_deinit(false); + callback(PNG_OK, image, callback_data); } else if (err != SPNG_OK) { png_callback_t *callback = decoder->callback; void *callback_data = decoder->callback_data; diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index e4e22ef9d..b071477cd 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -898,6 +898,7 @@ static bool load_metadata_from_zip_file (const char *zip_path, rom_info_t *rom_i bool success = false; if (meta_ini) { bool ok = true; + ok &= replace_owned_string(&rom_info->meta.metadata_zip_path, zip_path); ok &= replace_owned_string(&rom_info->meta.name, ini_get_string(meta_ini, "meta", "name", "")); ok &= replace_owned_string(&rom_info->meta.author, ini_get_string(meta_ini, "meta", "author", "Not specified")); ok &= replace_owned_string(&rom_info->meta.release_date, ini_get_string(meta_ini, "meta", "release-date", "Not specified")); @@ -906,6 +907,34 @@ static bool load_metadata_from_zip_file (const char *zip_path, rom_info_t *rom_i rom_info->meta.age_rating = ini_get_int(meta_ini, "meta", "age-rating", 0); rom_info->meta.num_players = ini_get_int(meta_ini, "meta", "num-players", 1); ok &= replace_owned_string(&rom_info->meta.short_description, ini_get_string(meta_ini, "meta", "short-desc", "")); + static const char *boxart_keys[] = { "front", "back", "top", "bottom", "left", "right" }; + for (size_t i = 0; i < 6; i++) { + ok &= replace_owned_string(&rom_info->meta.boxart[i], ini_get_string(meta_ini, "boxart", boxart_keys[i], "")); + } + for (size_t i = 0; i < rom_info->meta.screenshot_count; i++) { + free(rom_info->meta.screenshots[i]); + rom_info->meta.screenshots[i] = NULL; + } + rom_info->meta.screenshot_count = 0; + const char *screenshots = ini_get_string(meta_ini, "meta", "screenshots", ""); + char *list = strdup(screenshots); + if (list != NULL) { + char *save = NULL; + for (char *filename = strtok_r(list, ",", &save); + filename != NULL && rom_info->meta.screenshot_count < ROM_METADATA_MAX_SCREENSHOTS; + filename = strtok_r(NULL, ",", &save)) { + while (*filename == ' ' || *filename == '\t') filename++; + char *end = filename + strlen(filename); + while (end > filename && (end[-1] == ' ' || end[-1] == '\t')) *--end = '\0'; + if (*filename != '\0') { + rom_info->meta.screenshots[rom_info->meta.screenshot_count] = strdup(filename); + if (rom_info->meta.screenshots[rom_info->meta.screenshot_count] != NULL) { + rom_info->meta.screenshot_count++; + } + } + } + free(list); + } ini_free(meta_ini); success = ok; if (ok) { @@ -1049,6 +1078,7 @@ static bool load_rom_meta_from_embedded_zip (const char *rom_path, rom_header_t bool success = false; if (meta_ini) { bool ok = true; + ok &= replace_owned_string(&rom_info->meta.metadata_zip_path, rom_path); ok &= replace_owned_string(&rom_info->meta.name, ini_get_string(meta_ini, "meta", "name", "")); ok &= replace_owned_string(&rom_info->meta.author, ini_get_string(meta_ini, "meta", "author", "Not specified")); ok &= replace_owned_string(&rom_info->meta.release_date, ini_get_string(meta_ini, "meta", "release-date", "Not specified")); @@ -1058,6 +1088,34 @@ static bool load_rom_meta_from_embedded_zip (const char *rom_path, rom_header_t rom_info->meta.num_players = ini_get_int(meta_ini, "meta", "num-players", 1); ok &= replace_owned_string(&rom_info->meta.short_description, ini_get_string(meta_ini, "meta", "short-desc", "")); ok &= replace_owned_string(&rom_info->meta.long_description_fn, ini_get_string(meta_ini, "meta", "long-desc-fn", "")); + static const char *boxart_keys[] = { "front", "back", "top", "bottom", "left", "right" }; + for (size_t i = 0; i < 6; i++) { + ok &= replace_owned_string(&rom_info->meta.boxart[i], ini_get_string(meta_ini, "boxart", boxart_keys[i], "")); + } + for (size_t i = 0; i < rom_info->meta.screenshot_count; i++) { + free(rom_info->meta.screenshots[i]); + rom_info->meta.screenshots[i] = NULL; + } + rom_info->meta.screenshot_count = 0; + const char *screenshots = ini_get_string(meta_ini, "meta", "screenshots", ""); + char *list = strdup(screenshots); + if (list != NULL) { + char *save = NULL; + for (char *filename = strtok_r(list, ",", &save); + filename != NULL && rom_info->meta.screenshot_count < ROM_METADATA_MAX_SCREENSHOTS; + filename = strtok_r(NULL, ",", &save)) { + while (*filename == ' ' || *filename == '\t') filename++; + char *end = filename + strlen(filename); + while (end > filename && (end[-1] == ' ' || end[-1] == '\t')) *--end = '\0'; + if (*filename != '\0') { + rom_info->meta.screenshots[rom_info->meta.screenshot_count] = strdup(filename); + if (rom_info->meta.screenshots[rom_info->meta.screenshot_count] != NULL) { + rom_info->meta.screenshot_count++; + } + } + } + free(list); + } ini_free(meta_ini); success = ok; if (ok) { @@ -1128,6 +1186,34 @@ static void load_rom_meta_from_file (path_t *path, rom_info_t *rom_info) { rom_info->meta.num_players = ini_get_int(rom_meta_ini, "meta", "num-players", 1); ok &= replace_owned_string(&rom_info->meta.short_description, ini_get_string(rom_meta_ini, "meta", "short-desc", "")); ok &= replace_owned_string(&rom_info->meta.long_description_fn, ini_get_string(rom_meta_ini, "meta", "long-desc-fn", "")); + static const char *boxart_keys[] = { "front", "back", "top", "bottom", "left", "right" }; + for (size_t i = 0; i < 6; i++) { + ok &= replace_owned_string(&rom_info->meta.boxart[i], ini_get_string(rom_meta_ini, "boxart", boxart_keys[i], "")); + } + for (size_t i = 0; i < rom_info->meta.screenshot_count; i++) { + free(rom_info->meta.screenshots[i]); + rom_info->meta.screenshots[i] = NULL; + } + rom_info->meta.screenshot_count = 0; + const char *screenshots = ini_get_string(rom_meta_ini, "meta", "screenshots", ""); + char *list = strdup(screenshots); + if (list != NULL) { + char *save = NULL; + for (char *filename = strtok_r(list, ",", &save); + filename != NULL && rom_info->meta.screenshot_count < ROM_METADATA_MAX_SCREENSHOTS; + filename = strtok_r(NULL, ",", &save)) { + while (*filename == ' ' || *filename == '\t') filename++; + char *end = filename + strlen(filename); + while (end > filename && (end[-1] == ' ' || end[-1] == '\t')) *--end = '\0'; + if (*filename != '\0') { + rom_info->meta.screenshots[rom_info->meta.screenshot_count] = strdup(filename); + if (rom_info->meta.screenshots[rom_info->meta.screenshot_count] != NULL) { + rom_info->meta.screenshot_count++; + } + } + } + free(list); + } ini_free(rom_meta_ini); if (ok) { debugf("[META] Loaded from INI file: name='%s', author='%s'\n", rom_info->meta.name, rom_info->meta.author); @@ -1139,6 +1225,36 @@ static void load_rom_meta_from_file (path_t *path, rom_info_t *rom_info) { path_free(rom_info_meta_path); } +bool rom_info_extract_metadata_image(const rom_info_t *rom_info, const char *filename, + uint8_t **data, size_t *size) { + if (!rom_info || !rom_info->meta.metadata_zip_path || !filename || !data || !size || + filename[0] == '/' || strstr(filename, "..") != NULL) { + return false; + } + + *data = NULL; + *size = 0; + mz_zip_archive zip = {0}; + if (!mz_zip_reader_init_file(&zip, rom_info->meta.metadata_zip_path, 0)) return false; + + mz_uint index = mz_zip_reader_locate_file(&zip, filename, NULL, MZ_ZIP_FLAG_CASE_SENSITIVE); + mz_zip_archive_file_stat stat; + bool ok = index != MZ_UINT32_MAX && mz_zip_reader_file_stat(&zip, index, &stat) && + stat.m_uncomp_size > 0 && stat.m_uncomp_size <= 2 * 1024 * 1024; + if (ok) { + uint8_t *buffer = malloc((size_t) stat.m_uncomp_size); + ok = buffer != NULL && mz_zip_reader_extract_to_mem(&zip, index, buffer, (size_t) stat.m_uncomp_size, 0); + if (ok) { + *data = buffer; + *size = (size_t) stat.m_uncomp_size; + } else { + free(buffer); + } + } + mz_zip_reader_end(&zip); + return ok; +} + void rom_info_free_meta(rom_info_t *rom_info) { if (!rom_info) { return; @@ -1172,6 +1288,17 @@ void rom_info_free_meta(rom_info_t *rom_info) { free(rom_info->meta.long_description_fn); rom_info->meta.long_description_fn = NULL; } + free(rom_info->meta.metadata_zip_path); + rom_info->meta.metadata_zip_path = NULL; + for (size_t i = 0; i < 6; i++) { + free(rom_info->meta.boxart[i]); + rom_info->meta.boxart[i] = NULL; + } + for (size_t i = 0; i < rom_info->meta.screenshot_count; i++) { + free(rom_info->meta.screenshots[i]); + rom_info->meta.screenshots[i] = NULL; + } + rom_info->meta.screenshot_count = 0; } static void load_rom_config_from_file (path_t *path, rom_info_t *rom_info) { diff --git a/src/menu/rom_info.h b/src/menu/rom_info.h index e96fb3a77..f768e5b2b 100644 --- a/src/menu/rom_info.h +++ b/src/menu/rom_info.h @@ -9,10 +9,13 @@ #define ROM_INFO_H__ #include +#include #include #include "path.h" +#define ROM_METADATA_MAX_SCREENSHOTS 8 + /** @brief ROM error enumeration. */ typedef enum { ROM_OK, /**< No error */ @@ -175,10 +178,18 @@ typedef struct { uint32_t num_players; /**< The number of players supported */ char *short_description; /**< The short game description */ char *long_description_fn; /**< The long game description file name */ + char *metadata_zip_path; /**< ZIP containing metadata images, if any */ + char *boxart[6]; /**< Spec-defined boxart filenames: front, back, top, bottom, left, right */ + char *screenshots[ROM_METADATA_MAX_SCREENSHOTS]; /**< Spec-defined screenshot filenames */ + uint8_t screenshot_count; /**< Number of screenshot filenames */ bool size_limit_exceeded; /**< Metadata was skipped because metadata.ini exceeded size cap */ } meta; /**< The ROM metadata */ } rom_info_t; +/** Extract a metadata image from the associated ZIP into a heap buffer. */ +bool rom_info_extract_metadata_image(const rom_info_t *rom_info, const char *filename, + uint8_t **data, size_t *size); + /** * @brief Get the CIC seed for the ROM. * diff --git a/src/menu/ui_components.h b/src/menu/ui_components.h index e6f25e8c0..0d3bccef2 100644 --- a/src/menu/ui_components.h +++ b/src/menu/ui_components.h @@ -329,6 +329,10 @@ typedef struct { */ component_boxart_t *ui_components_boxart_init(const char *storage_prefix, const char *game_code, const char *rom_title, file_image_type_t current_image_view); +/** Initialize boxart from an image buffer owned by the decoder. */ +component_boxart_t *ui_components_boxart_init_mem(const char *filename, void *data, size_t size, + int max_width, int max_height); + /** * @brief Free the box art component resources. * diff --git a/src/menu/ui_components/background.c b/src/menu/ui_components/background.c index cb905c296..a1ad92ba1 100644 --- a/src/menu/ui_components/background.c +++ b/src/menu/ui_components/background.c @@ -63,7 +63,17 @@ static void load_from_cache(component_background_t *c) { } c->image = calloc(1, sizeof(surface_t)); + if (c->image == NULL) { + fclose(f); + return; + } *c->image = surface_alloc(FMT_RGBA16, cache_metadata.width, cache_metadata.height); + if (c->image->buffer == NULL) { + free(c->image); + c->image = NULL; + fclose(f); + return; + } if (cache_metadata.size != (c->image->height * c->image->stride)) { surface_free(c->image); diff --git a/src/menu/ui_components/boxart.c b/src/menu/ui_components/boxart.c index 9248e4a3a..3712d3204 100644 --- a/src/menu/ui_components/boxart.c +++ b/src/menu/ui_components/boxart.c @@ -8,6 +8,7 @@ #include "../ui_components.h" #include "../path.h" +#include "../jpeg_decoder.h" #include "../png_decoder.h" #include "constants.h" #include "utils/fs.h" @@ -31,6 +32,37 @@ static void png_decoder_callback(png_err_t err, surface_t *decoded_image, void * b->image = decoded_image; } +static void jpeg_decoder_callback(jpeg_err_t err, surface_t *decoded_image, void *callback_data) { + component_boxart_t *b = (component_boxart_t *)(callback_data); + b->loading = false; + b->image = (err == JPEG_OK) ? decoded_image : NULL; +} + +component_boxart_t *ui_components_boxart_init_mem(const char *filename, void *data, size_t size, + int max_width, int max_height) { + component_boxart_t *b = calloc(1, sizeof(component_boxart_t)); + if (!b) { + free(data); + return NULL; + } + b->loading = true; + + jpeg_err_t jpeg_err = JPEG_ERR_BAD_FILE; + png_err_t png_err = PNG_ERR_BAD_FILE; + bool is_jpeg = file_has_extensions((char *) filename, (const char *[]) { "jpg", "jpeg", NULL }); + if (is_jpeg) { + jpeg_err = jpeg_decoder_start_mem(data, size, max_width, max_height, jpeg_decoder_callback, b); + if (jpeg_err == JPEG_OK) return b; + } else { + png_err = png_decoder_start_mem(data, size, max_width, max_height, png_decoder_callback, b); + if (png_err == PNG_OK) return b; + if (png_err == PNG_ERR_BUSY) free(data); + } + + free(b); + return NULL; +} + /** * @brief Initialize and load the boxart component for a game. * @@ -180,6 +212,7 @@ component_boxart_t *ui_components_boxart_init(const char *storage_prefix, const void ui_components_boxart_free(component_boxart_t *b) { if (b) { if (b->loading) { + jpeg_decoder_abort(); png_decoder_abort(); } if (b->image) { diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index decc8ebd7..33f9048ea 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -5,6 +5,7 @@ #include "../sound.h" #include "boot/boot.h" #include "utils/fs.h" +#include "../ui_components/constants.h" #include "views.h" #include @@ -15,7 +16,7 @@ static component_boxart_t *boxart; static char *rom_filename = NULL; static int16_t current_metadata_image_index = 0; -static const file_image_type_t metadata_image_filename_cache[] = { +static const file_image_type_t metadata_image_types[] = { IMAGE_BOXART_FRONT, IMAGE_BOXART_BACK, IMAGE_BOXART_LEFT, @@ -25,8 +26,12 @@ static const file_image_type_t metadata_image_filename_cache[] = { IMAGE_GAMEPAK_FRONT, IMAGE_GAMEPAK_BACK }; -static const uint16_t metadata_image_filename_cache_length = sizeof(metadata_image_filename_cache) / sizeof(metadata_image_filename_cache[0]); -static bool metadata_image_available[sizeof(metadata_image_filename_cache) / sizeof(metadata_image_filename_cache[0])] = {false}; +#define METADATA_IMAGE_CACHE_MAX (14) +static const uint16_t metadata_image_type_count = sizeof(metadata_image_types) / sizeof(metadata_image_types[0]); +static const char *metadata_image_names[METADATA_IMAGE_CACHE_MAX]; +static bool metadata_image_embedded[METADATA_IMAGE_CACHE_MAX]; +static bool metadata_image_available[METADATA_IMAGE_CACHE_MAX]; +static uint16_t metadata_image_count; static bool metadata_images_scanned = false; static void scan_metadata_images(menu_t *menu) { @@ -34,6 +39,26 @@ static void scan_metadata_images(menu_t *menu) { return; } + metadata_image_count = 0; + if (menu->load.rom_info.meta.metadata_zip_path) { + for (uint16_t i = 0; i < 6 && metadata_image_count < METADATA_IMAGE_CACHE_MAX; i++) { + if (menu->load.rom_info.meta.boxart[i] && menu->load.rom_info.meta.boxart[i][0]) { + metadata_image_names[metadata_image_count] = menu->load.rom_info.meta.boxart[i]; + metadata_image_embedded[metadata_image_count] = true; + metadata_image_available[metadata_image_count++] = true; + } + } + for (uint16_t i = 0; i < menu->load.rom_info.meta.screenshot_count && metadata_image_count < METADATA_IMAGE_CACHE_MAX; i++) { + metadata_image_names[metadata_image_count] = menu->load.rom_info.meta.screenshots[i]; + metadata_image_embedded[metadata_image_count] = true; + metadata_image_available[metadata_image_count++] = true; + } + if (metadata_image_count > 0) { + metadata_images_scanned = true; + return; + } + } + path_t *path = path_init(menu->storage_prefix, "menu/metadata"); // should be METADATA_BASE_DIRECTORY char game_code_path[50]; @@ -63,7 +88,7 @@ static void scan_metadata_images(menu_t *menu) { bool dir_exists = directory_exists(path_get(path)); if (dir_exists) { - // Filenames array matches metadata_image_filename_cache order for indexed access + // Filenames array matches metadata_image_types order for indexed access // Note: This mapping is also present in boxart.c but duplicated here // for efficient scanning without calling into the component layer char *filenames[] = { @@ -77,14 +102,18 @@ static void scan_metadata_images(menu_t *menu) { "gamepak_back.png" }; - for (uint16_t i = 0; i < metadata_image_filename_cache_length; i++) { + for (uint16_t i = 0; i < metadata_image_type_count; i++) { path_push(path, filenames[i]); + metadata_image_names[i] = filenames[i]; + metadata_image_embedded[i] = false; metadata_image_available[i] = file_exists(path_get(path)); path_pop(path); } + metadata_image_count = metadata_image_type_count; } else { // No directory exists, mark all images as unavailable - for (uint16_t i = 0; i < metadata_image_filename_cache_length; i++) { + metadata_image_count = metadata_image_type_count; + for (uint16_t i = 0; i < metadata_image_count; i++) { metadata_image_available[i] = false; } } @@ -346,12 +375,13 @@ static void add_favorite (menu_t *menu, void *arg) { static void iterate_metadata_image(menu_t *menu, int direction) { scan_metadata_images(menu); + if (metadata_image_count == 0) return; bool low_memory_mode = !is_memory_expanded(); int16_t previous_metadata_image_index = current_metadata_image_index; // Transverse to next/previous available image based on direction (1 = next, -1 = previous) int16_t start_metadata_image_index = current_metadata_image_index; - int16_t new_metadata_image_index = (current_metadata_image_index + direction + metadata_image_filename_cache_length) % metadata_image_filename_cache_length; + int16_t new_metadata_image_index = (current_metadata_image_index + direction + metadata_image_count) % metadata_image_count; // Find next available image from our cached list while (new_metadata_image_index != start_metadata_image_index) { @@ -362,13 +392,33 @@ static void iterate_metadata_image(menu_t *menu, int direction) { boxart = NULL; } - // ui_components_boxart_init returns NULL if PNG decoder is busy - component_boxart_t *new_boxart = ui_components_boxart_init( - menu->storage_prefix, - menu->load.rom_info.game_code, - menu->load.rom_info.title, - metadata_image_filename_cache[new_metadata_image_index] - ); + component_boxart_t *new_boxart = NULL; + if (metadata_image_embedded[new_metadata_image_index]) { + uint8_t *data = NULL; + size_t size = 0; + if (!is_memory_expanded()) { + ui_components_background_image_free_only(); + } + if (rom_info_extract_metadata_image( + &menu->load.rom_info, + metadata_image_names[new_metadata_image_index], + &data, &size)) { + new_boxart = ui_components_boxart_init_mem( + metadata_image_names[new_metadata_image_index], data, size, + BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX + ); + } + if (new_boxart == NULL) { + ui_components_background_reload(); + } + } else { + new_boxart = ui_components_boxart_init( + menu->storage_prefix, + menu->load.rom_info.game_code, + menu->load.rom_info.title, + metadata_image_types[new_metadata_image_index] + ); + } if (new_boxart != NULL) { // Only free old boxart after successful new allocation @@ -382,12 +432,32 @@ static void iterate_metadata_image(menu_t *menu, int direction) { } else if (low_memory_mode) { // Best effort restore of previous image after a failed low-memory swap. if (metadata_image_available[previous_metadata_image_index]) { - boxart = ui_components_boxart_init( - menu->storage_prefix, - menu->load.rom_info.game_code, - menu->load.rom_info.title, - metadata_image_filename_cache[previous_metadata_image_index] - ); + if (metadata_image_embedded[previous_metadata_image_index]) { + uint8_t *data = NULL; + size_t size = 0; + if (!is_memory_expanded()) { + ui_components_background_image_free_only(); + } + if (rom_info_extract_metadata_image( + &menu->load.rom_info, + metadata_image_names[previous_metadata_image_index], + &data, &size)) { + boxart = ui_components_boxart_init_mem( + metadata_image_names[previous_metadata_image_index], data, size, + BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX + ); + } + if (boxart == NULL) { + ui_components_background_reload(); + } + } else { + boxart = ui_components_boxart_init( + menu->storage_prefix, + menu->load.rom_info.game_code, + menu->load.rom_info.title, + metadata_image_types[previous_metadata_image_index] + ); + } } if (boxart == NULL) { menu_show_error(menu, "Could not swap boxart image"); @@ -395,7 +465,7 @@ static void iterate_metadata_image(menu_t *menu, int direction) { break; } } - new_metadata_image_index = (new_metadata_image_index + direction + metadata_image_filename_cache_length) % metadata_image_filename_cache_length; + new_metadata_image_index = (new_metadata_image_index + direction + metadata_image_count) % metadata_image_count; } } @@ -842,12 +912,16 @@ static void load (menu_t *menu) { static void deinit (void) { ui_components_boxart_free(boxart); boxart = NULL; + ui_components_background_reload(); current_metadata_image_index = 0; metadata_images_scanned = false; + metadata_image_count = 0; // Clear availability cache - for (uint16_t i = 0; i < metadata_image_filename_cache_length; i++) { + for (uint16_t i = 0; i < METADATA_IMAGE_CACHE_MAX; i++) { metadata_image_available[i] = false; + metadata_image_embedded[i] = false; + metadata_image_names[i] = NULL; } } @@ -908,7 +982,28 @@ void view_load_rom_init (menu_t *menu) { if (!menu->settings.rom_autoload_enabled) { #endif current_metadata_image_index = 0; - boxart = ui_components_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, menu->load.rom_info.title, IMAGE_BOXART_FRONT); + scan_metadata_images(menu); + if (metadata_image_count > 0 && metadata_image_available[0] && metadata_image_embedded[0]) { + uint8_t *data = NULL; + size_t size = 0; + if (!is_memory_expanded()) { + ui_components_background_image_free_only(); + } + if (rom_info_extract_metadata_image(&menu->load.rom_info, metadata_image_names[0], &data, &size)) { + boxart = ui_components_boxart_init_mem( + metadata_image_names[0], data, size, + BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX + ); + } + if (boxart == NULL) { + ui_components_background_reload(); + } + } else { + boxart = ui_components_boxart_init( + menu->storage_prefix, menu->load.rom_info.game_code, + menu->load.rom_info.title, IMAGE_BOXART_FRONT + ); + } ui_components_context_menu_init(&options_context_menu); #ifdef FEATURE_AUTOLOAD_ROM_ENABLED } @@ -919,6 +1014,10 @@ void view_load_rom_init (menu_t *menu) { void view_load_rom_display (menu_t *menu, surface_t *display) { process(menu); + if (!is_memory_expanded() && boxart != NULL && !boxart->loading && boxart->image == NULL) { + ui_components_background_reload(); + } + draw(menu, display); if (menu->load_pending.rom_file) {