diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 116f0cb9..e5a3ad30 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ FROM debian:bookworm-slim -ARG SC64_DEPLOYER_VERSION=v2.18.0 +ARG SC64_DEPLOYER_VERSION=v2.20.0 RUN apt-get update && \ apt-get upgrade -y && \ apt-get install build-essential doxygen git python3 wget -y && \ diff --git a/Makefile b/Makefile index 55826de7..2265c991 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,6 @@ $(SPNG_OBJS): N64_CFLAGS+=-isystem $(SOURCE_DIR)/libs/miniz -DSPNG_USE_MINIZ -fc $(FILESYSTEM_DIR)/FiraMonoBold.font64: MKFONT_FLAGS+=-c 1 --size 16 -r 20-7F -r 80-1FF -r 2026-2026 --ellipsis 2026,1 $(FILESYSTEM_DIR)/%.wav64: AUDIOCONV_FLAGS=--wav-compress 1 - $(@info $(shell mkdir -p ./$(FILESYSTEM_DIR) &> /dev/null)) $(FILESYSTEM_DIR)/%.font64: $(ASSETS_DIR)/%.ttf diff --git a/README.md b/README.md index 703804cc..de3d030c 100644 --- a/README.md +++ b/README.md @@ -49,22 +49,45 @@ 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: +* [Japan Boxart](https://mega.nz/file/KyJR0B6B#ERabLautAVPaqJTIdBSv4ghbudNhK7hnEr2ZS1Q6ub0) +* [American Boxart](https://mega.nz/file/rugAFYSQ#JHfgCU2amzNVpC4S6enP3vg--wtAAwsziKa7cej6QCc) +* [European Boxart](https://mega.nz/file/OmIV3aAK#kOWdutK1_41ffN64R6thbU7HEPR_M9qO0YM2mNG6RbQ) +* [64DD Boxart](https://mega.nz/file/ay5wQIxJ#k3PF-VMLrZJxJTr-BOaOKa2TBIK7c2t4zwbdshsQl40) ### Menu Settings diff --git a/docs/00_getting_started_sd.md b/docs/00_getting_started_sd.md index 4ee6e763..af937dfe 100644 --- a/docs/00_getting_started_sd.md +++ b/docs/00_getting_started_sd.md @@ -36,7 +36,7 @@ SD:\ │ │ ├── NDDJ2.n64 │ │ └── NDXJ0.n64 │ │ -│ └── emulators +│ └── emulators\ │ ├── neon64bu.rom │ ├── sodium64.z64 │ ├── gb.v64 diff --git a/docs/99_developer_guide.md b/docs/99_developer_guide.md index ff6ad67c..ab148140 100644 --- a/docs/99_developer_guide.md +++ b/docs/99_developer_guide.md @@ -8,11 +8,11 @@ You can use a dev container in VSCode to ease development. ### To deploy: #### SC64 -* Download the deployer [here](https://github.com/Polprzewodnikowy/SummerCart64/releases/download/v2.18.0/sc64-deployer-windows-v2.18.0.zip) +* Download the deployer [here](https://github.com/Polprzewodnikowy/SummerCart64/releases/download/v2.20.0/sc64-deployer-windows-v2.20.0.zip) * Extract and place `sc64deployer.exe` in the `tools/sc64` directory. -Make sure that your firmware is compatible (currently v2.18.0+) -See: [here](https://github.com/Polprzewodnikowy/SummerCart64/blob/v2.18.0/docs/00_quick_startup_guide.md#firmware-backupupdate) +Make sure that your firmware is compatible (currently v2.20.0+) +See: [here](https://github.com/Polprzewodnikowy/SummerCart64/blob/v2.20.0/docs/00_quick_startup_guide.md#firmware-backupupdate) ##### From the devcontainer It is not currently possible to directly communicate with USB devices. diff --git a/libdragon b/libdragon index 9bae4999..9dd99415 160000 --- a/libdragon +++ b/libdragon @@ -1 +1 @@ -Subproject commit 9bae49994bf1c796f9939ea1aa7c133813b9053f +Subproject commit 9dd994151ae3f3709f1f80224e6b654aac8be6b4 diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index 0fd47bef..3997bf80 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -75,6 +75,8 @@ static bool d64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_64DD: return false; case FLASHCART_FEATURE_RTC: return true; case FLASHCART_FEATURE_USB: return true; + case FLASHCART_FEATURE_AUTO_CIC: return true; + case FLASHCART_FEATURE_AUTO_REGION: return true; default: return false; } } diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index b4996f36..ade09eaa 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -29,6 +29,8 @@ typedef enum { FLASHCART_FEATURE_64DD, FLASHCART_FEATURE_RTC, FLASHCART_FEATURE_USB, + FLASHCART_FEATURE_AUTO_CIC, + FLASHCART_FEATURE_AUTO_REGION, } flashcart_features_t; /** @brief Flashcart save type enumeration */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index 7119a271..bcab63f0 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -254,6 +254,8 @@ static bool sc64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_64DD: return true; case FLASHCART_FEATURE_RTC: return true; case FLASHCART_FEATURE_USB: return true; + case FLASHCART_FEATURE_AUTO_CIC: return true; + case FLASHCART_FEATURE_AUTO_REGION: return true; default: return false; } } diff --git a/src/libs/miniz b/src/libs/miniz index 16413c21..1ff82be7 160000 --- a/src/libs/miniz +++ b/src/libs/miniz @@ -1 +1 @@ -Subproject commit 16413c213de38e703d883006193734e8b1178d5d +Subproject commit 1ff82be7d67f5c2f8b5497f538eea247861e0717 diff --git a/src/menu/actions.c b/src/menu/actions.c index 14c87fb6..00317168 100644 --- a/src/menu/actions.c +++ b/src/menu/actions.c @@ -25,8 +25,16 @@ static void actions_clear (menu_t *menu) { } static void actions_update_direction (menu_t *menu) { - joypad_8way_t held_dir = joypad_get_direction(JOYPAD_PORT_1, JOYPAD_2D_DPAD | JOYPAD_2D_STICK); - joypad_8way_t fast_dir = joypad_get_direction(JOYPAD_PORT_1, JOYPAD_2D_C); + joypad_8way_t held_dir; + joypad_8way_t fast_dir; + + JOYPAD_PORT_FOREACH (i) { + held_dir = joypad_get_direction(i, JOYPAD_2D_DPAD | JOYPAD_2D_STICK); + fast_dir = joypad_get_direction(i, JOYPAD_2D_C); + if (held_dir != JOYPAD_8WAY_NONE || fast_dir != JOYPAD_8WAY_NONE) { + break; + } + } if (fast_dir != JOYPAD_8WAY_NONE) { held_dir = fast_dir; @@ -82,7 +90,14 @@ static void actions_update_direction (menu_t *menu) { } static void actions_update_buttons (menu_t *menu) { - joypad_buttons_t pressed = joypad_get_buttons_pressed(JOYPAD_PORT_1); + joypad_buttons_t pressed; + + JOYPAD_PORT_FOREACH (i) { + pressed = joypad_get_buttons_pressed(i); + if (pressed.raw) { + break; + } + } if (pressed.a) { menu->actions.enter = true; @@ -98,6 +113,12 @@ static void actions_update_buttons (menu_t *menu) { } +void actions_init (void) { + JOYPAD_PORT_FOREACH (port) { + joypad_set_rumble_active(port, false); + } +} + void actions_update (menu_t *menu) { joypad_poll(); diff --git a/src/menu/actions.h b/src/menu/actions.h index f890b55c..e02e35af 100644 --- a/src/menu/actions.h +++ b/src/menu/actions.h @@ -11,6 +11,7 @@ #include "menu_state.h" +void actions_init (void); void actions_update (menu_t *menu); diff --git a/src/menu/components.h b/src/menu/components.h index 4925ee5b..67fde2d3 100644 --- a/src/menu/components.h +++ b/src/menu/components.h @@ -11,6 +11,41 @@ #include #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); diff --git a/src/menu/components/background.c b/src/menu/components/background.c index 45119107..525fb0c8 100644 --- a/src/menu/components/background.c +++ b/src/menu/components/background.c @@ -98,9 +98,6 @@ static void prepare_background (component_background_t *c) { return; } - uint16_t image_center_x = (c->image->width / 2); - uint16_t image_center_y = (c->image->height / 2); - // Darken the image rdpq_attach(c->image, NULL); rdpq_mode_push(); @@ -108,15 +105,13 @@ static void prepare_background (component_background_t *c) { rdpq_set_prim_color(BACKGROUND_OVERLAY_COLOR); rdpq_mode_combiner(RDPQ_COMBINER_FLAT); rdpq_mode_blender(RDPQ_BLENDER_MULTIPLY); - rdpq_fill_rectangle( - 0 - (DISPLAY_CENTER_X - image_center_x), - 0 - (DISPLAY_CENTER_Y - image_center_y), - DISPLAY_WIDTH - (DISPLAY_CENTER_X - image_center_x), - DISPLAY_HEIGHT - (DISPLAY_CENTER_Y - image_center_y) - ); + rdpq_fill_rectangle(0, 0, c->image->width, c->image->height); rdpq_mode_pop(); rdpq_detach(); + uint16_t image_center_x = (c->image->width / 2); + uint16_t image_center_y = (c->image->height / 2); + // Prepare display list rspq_block_begin(); rdpq_mode_push(); diff --git a/src/menu/components/boxart.c b/src/menu/components/boxart.c index f50294ee..2535068c 100644 --- a/src/menu/components/boxart.c +++ b/src/menu/components/boxart.c @@ -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 ); } -} \ No newline at end of file +} diff --git a/src/menu/menu.c b/src/menu/menu.c index 6f17a893..d431d8de 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -27,53 +27,19 @@ #define MENU_CACHE_DIRECTORY "cache" #define BACKGROUND_CACHE_FILE "background.data" -#define FRAMERATE_DIVIDER (2) -#define LAG_REPORT (false) +#define INTERLACED (true) +#define FPS_LIMIT (30.0f) static menu_t *menu; -static tv_type_t tv_type; -static volatile int frame_counter = 0; - -extern tv_type_t __boot_tvtype; -static void frame_counter_handler (void) { - frame_counter += 1; -} - -static void frame_counter_reset (void) { -#if LAG_REPORT - static int accumulated = 0; - if (frame_counter > FRAMERATE_DIVIDER) { - accumulated += frame_counter - FRAMERATE_DIVIDER; - debugf( - "LAG: %d additional frame(s) displayed since last draw (accumulated: %d)\n", - frame_counter - FRAMERATE_DIVIDER, - accumulated - ); - } -#endif - frame_counter = 0; -} - -static void menu_init (boot_params_t *boot_params) { - joypad_init(); - timer_init(); - rtc_init(); - rspq_init(); - rdpq_init(); - dfs_init(DFS_DEFAULT_LOCATION); - - sound_init_default(); - - JOYPAD_PORT_FOREACH (port) { - joypad_set_rumble_active(port, false); - } - +static void menu_init (boot_params_t *boot_params) { menu = calloc(1, sizeof(menu_t)); assert(menu != NULL); + menu->boot_params = boot_params; + menu->mode = MENU_MODE_NONE; menu->next_mode = MENU_MODE_STARTUP; @@ -82,6 +48,19 @@ static void menu_init (boot_params_t *boot_params) { menu->next_mode = MENU_MODE_FAULT; } + joypad_init(); + timer_init(); + rtc_init(); + rspq_init(); + rdpq_init(); + dfs_init(DFS_DEFAULT_LOCATION); + + actions_init(); + sound_init_default(); + sound_init_sfx(); + + hdmi_clear_game_id(); + path_t *path = path_init(menu->storage_prefix, MENU_DIRECTORY); directory_create(path_get(path)); @@ -91,6 +70,15 @@ static void menu_init (boot_params_t *boot_params) { settings_load(&menu->settings); path_pop(path); + resolution_t resolution = { + .width = 640, + .height = 480, + .interlaced = INTERLACED ? INTERLACE_HALF : INTERLACE_OFF, + .pal60 = menu->settings.pal60_enabled, + }; + display_init(resolution, DEPTH_16_BPP, 2, GAMMA_NONE, INTERLACED ? FILTERS_DISABLED : FILTERS_RESAMPLE); + display_set_fps_limit(FPS_LIMIT); + path_push(path, MENU_CUSTOM_FONT_FILE); fonts_init(path_get(path)); path_pop(path); @@ -103,40 +91,20 @@ static void menu_init (boot_params_t *boot_params) { path_free(path); - menu->boot_params = boot_params; + sound_use_sfx(menu->settings.sound_enabled); menu->browser.directory = path_init(menu->storage_prefix, menu->settings.default_directory); if (!directory_exists(path_get(menu->browser.directory))) { path_free(menu->browser.directory); menu->browser.directory = path_init(menu->storage_prefix, "/"); } - - hdmi_clear_game_id(); - - tv_type = get_tv_type(); - if ((tv_type == TV_PAL) && menu->settings.pal60_enabled) { - // HACK: Set TV type to NTSC, so PAL console would output 60 Hz signal instead. - __boot_tvtype = TV_NTSC; - } - - sound_init_sfx(); - if (menu->settings.sound_enabled) { - sound_use_sfx(true); - } - - display_init(RESOLUTION_640x480, DEPTH_16_BPP, 2, GAMMA_NONE, FILTERS_DISABLED); - - register_VI_handler(frame_counter_handler); } static void menu_deinit (menu_t *menu) { - unregister_VI_handler(frame_counter_handler); - - // NOTE: Restore previous TV type so boot procedure wouldn't passthrough wrong value. - __boot_tvtype = tv_type; - hdmi_send_game_id(menu->boot_params); + component_background_free(); + path_free(menu->load.disk_path); path_free(menu->load.rom_path); for (int i = 0; i < menu->browser.entries; i++) { @@ -146,9 +114,7 @@ static void menu_deinit (menu_t *menu) { path_free(menu->browser.directory); free(menu); - component_background_free(); - - flashcart_deinit(); + display_close(); sound_deinit(); @@ -158,7 +124,7 @@ static void menu_deinit (menu_t *menu) { timer_close(); joypad_close(); - display_close(); + flashcart_deinit(); } typedef const struct { @@ -201,11 +167,9 @@ void menu_run (boot_params_t *boot_params) { menu_init(boot_params); while (true) { - surface_t *display = (frame_counter >= FRAMERATE_DIVIDER) ? display_try_get() : NULL; + surface_t *display = display_try_get(); if (display != NULL) { - frame_counter_reset(); - actions_update(menu); view_t *view = menu_get_view(menu->mode); diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index 25f07832..e5b750ce 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -186,6 +186,9 @@ static const match_t database[] = { MATCH_ID_REGION("NDKJ", SAVE_TYPE_EEPROM_4KBIT, FEAT_NONE), // Dark Rift [Space Dynamites (J)] + MATCH_ID_REGION("NPDJ", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK | FEAT_RPAK | FEAT_TPAK | FEAT_EXP_PAK_REQUIRED),// Perfect Dark (J) + MATCH_ID("NPD", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK | FEAT_RPAK | FEAT_TPAK | FEAT_EXP_PAK_RECOMMENDED), // Perfect Dark + MATCH_ID_REGION("NSVE", SAVE_TYPE_EEPROM_4KBIT, FEAT_RPAK), // Space Station Silicon Valley MATCH_ID("NSV", SAVE_TYPE_EEPROM_4KBIT, FEAT_RPAK | FEAT_EXP_PAK_BROKEN), // Space Station Silicon Valley @@ -305,7 +308,6 @@ static const match_t database[] = { MATCH_ID("NMV", SAVE_TYPE_EEPROM_16KBIT, FEAT_RPAK), // Mario Party 3 MATCH_ID("NMX", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK | FEAT_RPAK), // Excitebike 64 MATCH_ID("NNB", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK | FEAT_RPAK), // Kobe Bryant in NBA Courtside - MATCH_ID("NPD", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK | FEAT_RPAK | FEAT_TPAK | FEAT_EXP_PAK_RECOMMENDED), // Perfect Dark MATCH_ID("NPP", SAVE_TYPE_EEPROM_16KBIT, FEAT_CPAK), // Parlor! Pro 64: Pachinko Jikki Simulation Game MATCH_ID("NR7", SAVE_TYPE_EEPROM_16KBIT, FEAT_TPAK), // Robot Poncots 64: 7tsu no Umi no Caramel MATCH_ID("NRZ", SAVE_TYPE_EEPROM_16KBIT, FEAT_RPAK), // Ridge Racer 64 diff --git a/src/menu/views/fault.c b/src/menu/views/fault.c index 7128f666..6ec767a4 100644 --- a/src/menu/views/fault.c +++ b/src/menu/views/fault.c @@ -7,7 +7,7 @@ static void draw (menu_t *menu, surface_t *d) { rdpq_clear(RGBA32(0x7F, 0x00, 0x00, 0xFF)); const char *firmware_message = ( - "Supported firmware versions:\n" + "Minimum supported firmware versions:\n" "64drive: 2.05+\n" "EverDrive-64: ???+\n" "SummerCart64: 2.17.0+" diff --git a/src/menu/views/load_disk.c b/src/menu/views/load_disk.c index 0165bdc9..39957fcf 100644 --- a/src/menu/views/load_disk.c +++ b/src/menu/views/load_disk.c @@ -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) { diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index c408b47c..36933b92 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -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); }