mirror of
https://github.com/Polprzewodnikowy/N64FlashcartMenu.git
synced 2024-11-22 10:39:20 +01:00
Optimize boxart image load (#130)
<!--- Provide a general summary of your changes in the Title above --> ## Description <!--- Describe your changes in detail --> Improves boxart image loading by using directory file paths. It also adds matching by full game ID's (for compatibility), but notes in the readme that it is slow. ## Motivation and Context <!--- What does this sample do? What problem does it solve? --> <!--- If it fixes/closes/resolves an open issue, please link to the issue here --> Loading boxart was slow in certain circumstances. ## How Has This Been Tested? <!-- (if applicable) --> <!--- Please describe in detail how you tested your sample/changes. --> <!--- Include details of your testing environment, and the tests you ran to --> <!--- see how your change affects other areas of the code, etc. --> Locally on an SC64. ## Screenshots <!-- (if appropriate): --> ## Types of changes <!--- What types of changes does your code introduce? Put an `x` in all the boxes that apply: --> - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Documentation Improvement - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: <!--- Go over all the following points, and put an `x` in all the boxes that apply. --> <!--- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> - [ ] My code follows the code style of this project. - [ ] My change requires a change to the documentation. - [ ] I have updated the documentation accordingly. - [ ] I have added tests to cover my changes. - [ ] All new and existing tests passed. <!--- It would be nice if you could sign off your contribution by replacing the name with your GitHub user name and GitHub email contact. --> Signed-off-by: GITHUB_USER <GITHUB_USER_EMAIL> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a new image type enumeration for boxart components, enhancing image management. - Updated boxart initialization to allow for specific image views, improving flexibility in image retrieval. - Enhanced instructions for setting up boxart images with clearer directory structures and simplified naming conventions. - **Bug Fixes** - Improved the logic for loading boxart images, enabling better fallback options in case of missing files. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
parent
d87dfb4ab2
commit
269a8ae94d
48
README.md
48
README.md
@ -49,22 +49,44 @@ An open source menu for N64 flashcarts.
|
||||
## Experimental features
|
||||
These features are subject to change:
|
||||
|
||||
### ROM Boxart
|
||||
To use boxart, place PNG files in the `/menu/boxart` folder on the SD card with the following dimensions:
|
||||
* Standard covers: 158x112
|
||||
* 64DD covers: 129x112
|
||||
* Japanese covers: 112x158
|
||||
|
||||
Each file must be named according to the 2 letter ROM ID, or 3 letter ROM ID including media type.
|
||||
i.e. for GoldenEye 2 letters, this would be `GE.png`.
|
||||
i.e. for GoldenEye 3 letters, this would be `NGE.png`.
|
||||
You can download these boxart packs:
|
||||
|
||||
[American Boxart](https://mega.nz/file/6cNGwSqI#8X5ukb65n3YMlGaUtSOGXkKo9HxVnnMOgqn94Epcr7w)
|
||||
### GamePak sprites
|
||||
To use N64 `GamePak` sprites, place `PNG` files within the `sd:/menu/boxart/` folder.
|
||||
|
||||
[European Boxart](https://mega.nz/file/O7AjDbRJ#VnVU10dq8HQvBUQptppI6PAcQMb8-Zembqav8WtAQ_M)
|
||||
|
||||
[64DD Boxart](https://mega.nz/file/O3JzwD7B#BYl1aV-pbrJ-MxWUbM_K0yGVIRbmSoxJJZqQInRzZyM)
|
||||
#### Supported sprites
|
||||
These must be `PNG` files that use the following dimensions:
|
||||
* Standard N64 GamePak boxart sprites: 158x112
|
||||
* Japanese N64 GamePak boxart sprites: 112x158
|
||||
* 64DD boxart sprites: 129x112
|
||||
|
||||
They will be loaded by directories using each character of the full 4 character Game Code (as identified in the menus ROM information).
|
||||
i.e. for GoldenEye NTSC USA (NGEE), this would be `sd:/menu/boxart/N/G/E/E/boxart_front.png`.
|
||||
i.e. for GoldenEye PAL (NGEP), this would be `sd:/menu/boxart/N/G/E/P/boxart_front.png`.
|
||||
|
||||
To improve compatibility between regions (as a fallback), you may exclude the region ID (last matched directory) for GamePaks to match with 3 letter IDs instead:
|
||||
i.e. for GoldenEye, this would be `sd:/menu/boxart/N/G/E/boxart_front.png`.
|
||||
|
||||
**Note1:** Excluding the region ID may show the wrong boxart.
|
||||
**Note2:** For future support, boxart sprites should also include: `boxart_back.png`, `boxart_top.png`, `boxart_bottom.png`, `boxart_left.png`, `boxart_right.png`.
|
||||
|
||||
|
||||
#### Compatibilty mode
|
||||
If you cannot yet satisfy the correct boxart layout, The menu still has **deprecated** support for filenames containing the Game ID.
|
||||
|
||||
**Note:** This will add a noticeable delay for displaying parts of the menu.
|
||||
|
||||
Each file must be named according to the 2,3 or 4 letter GamePak ID (matched in this order).
|
||||
i.e.
|
||||
* for GoldenEye 4 letters, this would be `sd:/menu/boxart/NGEE.png` and/or `sd:/menu/boxart/NGEP.png`.
|
||||
* for GoldenEye 3 letters, this would be `sd:/menu/boxart/NGE.png`.
|
||||
* for GoldenEye 2 letters, this would be `sd:/menu/boxart/GE.png`.
|
||||
|
||||
|
||||
As a starting point, here are some links to boxart packs:
|
||||
* [American GamePak Boxart](https://mega.nz/file/6cNGwSqI#8X5ukb65n3YMlGaUtSOGXkKo9HxVnnMOgqn94Epcr7w)
|
||||
* [European GamePak Boxart](https://mega.nz/file/O7AjDbRJ#VnVU10dq8HQvBUQptppI6PAcQMb8-Zembqav8WtAQ_M)
|
||||
* [64DD Boxart](https://mega.nz/file/O3JzwD7B#BYl1aV-pbrJ-MxWUbM_K0yGVIRbmSoxJJZqQInRzZyM)
|
||||
|
||||
|
||||
### Menu Settings
|
||||
|
@ -11,6 +11,41 @@
|
||||
#include <libdragon.h>
|
||||
#include "menu_state.h"
|
||||
|
||||
/** @brief File image Enumeration. */
|
||||
typedef enum {
|
||||
|
||||
/** @brief Boxart image from the front */
|
||||
IMAGE_BOXART_FRONT,
|
||||
|
||||
/** @brief Boxart image from the back */
|
||||
IMAGE_BOXART_BACK,
|
||||
|
||||
/** @brief Boxart image from the top */
|
||||
IMAGE_BOXART_TOP,
|
||||
|
||||
/** @brief Boxart image from the bottom */
|
||||
IMAGE_BOXART_BOTTOM,
|
||||
|
||||
/** @brief Boxart image from the left side */
|
||||
IMAGE_BOXART_LEFT,
|
||||
|
||||
/** @brief Boxart image from the right side */
|
||||
IMAGE_BOXART_RIGHT,
|
||||
|
||||
/** @brief GamePak image from the front */
|
||||
IMAGE_GAMEPAK_FRONT,
|
||||
|
||||
/** @brief GamePak image from the back */
|
||||
IMAGE_GAMEPAK_BACK,
|
||||
|
||||
/** @brief File image thumbnail */
|
||||
IMAGE_THUMBNAIL,
|
||||
|
||||
/** @brief List end marker */
|
||||
IMAGE_TYPE_END
|
||||
|
||||
} file_image_type_t;
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup
|
||||
@ -64,7 +99,7 @@ typedef struct {
|
||||
surface_t *image;
|
||||
} component_boxart_t;
|
||||
|
||||
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code);
|
||||
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code, file_image_type_t current_image_view);
|
||||
void component_boxart_free (component_boxart_t *b);
|
||||
void component_boxart_draw (component_boxart_t *b);
|
||||
|
||||
|
@ -17,9 +17,9 @@ static void png_decoder_callback (png_err_t err, surface_t *decoded_image, void
|
||||
}
|
||||
|
||||
|
||||
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code) {
|
||||
component_boxart_t *component_boxart_init (const char *storage_prefix, char *game_code, file_image_type_t current_image_view) {
|
||||
component_boxart_t *b;
|
||||
char file_name[8];
|
||||
char boxart_id_path[8];
|
||||
|
||||
if ((b = calloc(1, sizeof(component_boxart_t))) == NULL) {
|
||||
return NULL;
|
||||
@ -29,22 +29,84 @@ component_boxart_t *component_boxart_init (const char *storage_prefix, char *gam
|
||||
|
||||
path_t *path = path_init(storage_prefix, BOXART_DIRECTORY);
|
||||
|
||||
sprintf(file_name, "%.3s.png", game_code);
|
||||
path_push(path, file_name);
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
}
|
||||
path_pop(path);
|
||||
sprintf(boxart_id_path, "%c/%c/%c/%c", game_code[0], game_code[1], game_code[2], game_code[3]);
|
||||
path_push(path, boxart_id_path);
|
||||
|
||||
// TODO: This is bad, we should only check for 3 letter codes
|
||||
sprintf(file_name, "%.2s.png", game_code + 1);
|
||||
path_push(path, file_name);
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
if (!directory_exists(path_get(path))) { // Allow boxart to not specify the region code.
|
||||
path_pop(path);
|
||||
}
|
||||
|
||||
if (directory_exists(path_get(path))) {
|
||||
switch (current_image_view) {
|
||||
case IMAGE_GAMEPAK_FRONT:
|
||||
path_push(path, "gamepak_front.png");
|
||||
case IMAGE_GAMEPAK_BACK:
|
||||
path_push(path, "gamepak_back.png");
|
||||
case IMAGE_BOXART_BACK:
|
||||
path_push(path, "boxart_back.png");
|
||||
case IMAGE_BOXART_LEFT:
|
||||
path_push(path, "boxart_left.png");
|
||||
case IMAGE_BOXART_RIGHT:
|
||||
path_push(path, "boxart_right.png");
|
||||
case IMAGE_BOXART_BOTTOM:
|
||||
path_push(path, "boxart_bottom.png");
|
||||
case IMAGE_BOXART_TOP:
|
||||
path_push(path, "boxart_top.png");
|
||||
default:
|
||||
path_push(path, "boxart_front.png");
|
||||
}
|
||||
|
||||
if (file_exists(path_get(path))) {
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
else { // compatibility mode
|
||||
|
||||
char file_name[8];
|
||||
|
||||
// reset the directory path used for boxart.
|
||||
path = path_init(storage_prefix, BOXART_DIRECTORY);
|
||||
|
||||
sprintf(file_name, "%c%c%c%c.png", game_code[0], game_code[1], game_code[2], game_code[3]);
|
||||
path_push(path, file_name);
|
||||
|
||||
if (file_exists(path_get(path))) {
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
path_pop(path);
|
||||
sprintf(file_name, "%c%c%c.png", game_code[0], game_code[1], game_code[2]);
|
||||
path_push(path, file_name);
|
||||
|
||||
if (file_exists(path_get(path))) {
|
||||
if (file_exists(path_get(path))) {
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
path_pop(path);
|
||||
|
||||
sprintf(file_name, "%c%c.png", game_code[1], game_code[2]);
|
||||
path_push(path, file_name);
|
||||
if (file_exists(path_get(path))) {
|
||||
if (png_decoder_start(path_get(path), BOXART_WIDTH_MAX, BOXART_HEIGHT_MAX, png_decoder_callback, b) == PNG_OK) {
|
||||
path_free(path);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: return default image.
|
||||
|
||||
path_free(path);
|
||||
free(b);
|
||||
|
||||
@ -89,4 +151,4 @@ void component_boxart_draw (component_boxart_t *b) {
|
||||
BOXART_LOADING_COLOR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ void view_load_disk_init (menu_t *menu) {
|
||||
menu_show_error(menu, convert_error_message(err));
|
||||
}
|
||||
|
||||
boxart = component_boxart_init(menu->storage_prefix, menu->load.disk_info.id);
|
||||
boxart = component_boxart_init(menu->storage_prefix, menu->load.disk_info.id, IMAGE_BOXART_FRONT);
|
||||
}
|
||||
|
||||
void view_load_disk_display (menu_t *menu, surface_t *display) {
|
||||
|
@ -355,7 +355,7 @@ void view_load_rom_init (menu_t *menu) {
|
||||
return;
|
||||
}
|
||||
|
||||
boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code);
|
||||
boxart = component_boxart_init(menu->storage_prefix, menu->load.rom_info.game_code, IMAGE_BOXART_FRONT);
|
||||
|
||||
component_context_menu_init(&options_context_menu);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user