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/.github/workflows/build.yml b/.github/workflows/build.yml index b7da2151..7f88be12 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,7 +113,7 @@ jobs: - uses: actions/checkout@v4 - name: Run Doxygen - uses: mattnotmitt/doxygen-action@1.9.5 + uses: mattnotmitt/doxygen-action@v1 with: doxyfile-path: './Doxyfile' diff --git a/docs/00_getting_started_sd.md b/docs/00_getting_started_sd.md index af937dfe..f2f75de8 100644 --- a/docs/00_getting_started_sd.md +++ b/docs/00_getting_started_sd.md @@ -1,11 +1,19 @@ ## First time setup of SD card -Using your PC, insert the SD card and ensure it is formatted for compatibility with your flashcart (*FAT32 and EXFAT are fully supported on the SC64*). +Using your PC, insert the SD card and ensure it is formatted for compatibility with your flashcart +#### SC64 +- FAT32 and EXFAT are fully supported. +- An SD formatted with 128 kiB cluster size is recommended. - Download the latest `sc64menu.n64` (assuming you are using an *sc64*) file from the [releases](https://github.com/Polprzewodnikowy/N64FlashcartMenu/releases/) page, then put it in the root directory of your SD card. - Create a folder in the root of your SD card called `menu`. - Place your ROMs on the SD Card, in any folder (**except for `menu`**). +#### Other supported flashcarts +- FAT32 recommended. +- An SD formatted with default cluster size is recommended. + + ### Emulator support Emulators should be added to the `/menu/emulators` directory on the SD card. diff --git a/docs/99_developer_guide.md b/docs/99_developer_guide.md index ff6ad67c..8aa62879 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. @@ -45,10 +45,13 @@ For ease of development and debugging, the menu ROM can run in the [Ares emulato * Add the required file to the correct folder on your SD card. -## Update Libdragon submodule -This repo currently uses the `preview` branch as a submodule at a specific commit. +## Update submodules To update to the latest version, use `git submodule update --remote` from the terminal. +### libdragon +This repo currently uses the `preview` branch as a submodule at a specific commit. +* To ensure your local instance is building against it, use `cd ./libdragon && make clobber -j && make libdragon tools -j && make install tools-install -j && cd ..` + ## Generate documentation Run `doxygen` from the dev container terminal. Make sure you fix the warnings before creating a PR! @@ -57,6 +60,8 @@ Generated documentation is located in the `output/docs` folder and auto-publishe Once merged, they can be viewed [here](https://polprzewodnikowy.github.io/N64FlashcartMenu/) ### Test generated docs in the dev-container +Testing the documentation locally allows you to preview changes and ensure everything renders correctly before submitting your changes. + Install Prerequisites: ```bash apt-get install ruby-full build-essential zlib1g-dev diff --git a/src/boot/boot.c b/src/boot/boot.c index 9aaac778..2fc0a889 100644 --- a/src/boot/boot.c +++ b/src/boot/boot.c @@ -95,7 +95,7 @@ void boot (boot_params_t *params) { io32_t *reboot_dst = SP_MEM->IMEM; size_t reboot_instructions = (size_t) (&reboot_size) / sizeof(uint32_t); - for (int i = 0; i < reboot_instructions; i++) { + for (unsigned int i = 0; i < reboot_instructions; i++) { cpu_io_write(&reboot_dst[i], reboot_src[i]); } diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index 3997bf80..5b4b5d22 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -77,6 +77,7 @@ static bool d64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_REGION: return true; + case FLASHCART_FEATURE_SAVE_WRITEBACK: return true; default: return false; } } @@ -101,7 +102,7 @@ static flashcart_err_t d64_load_rom (char *rom_path, flashcart_progress_callback size_t sdram_size = MiB(64); size_t chunk_size = KiB(128); - for (int offset = 0; offset < sdram_size; offset += chunk_size) { + for (unsigned int offset = 0; offset < sdram_size; offset += chunk_size) { size_t block_size = MIN(sdram_size - offset, chunk_size); if (f_read(&fil, (void *) (ROM_ADDRESS + offset), block_size, &br) != FR_OK) { f_close(&fil); diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index ade09eaa..fcbcf606 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -31,6 +31,9 @@ typedef enum { FLASHCART_FEATURE_USB, FLASHCART_FEATURE_AUTO_CIC, FLASHCART_FEATURE_AUTO_REGION, + FLASHCART_FEATURE_DIAGNOSTIC_DATA, + FLASHCART_FEATURE_BIOS_UPDATE_FROM_MENU, + FLASHCART_FEATURE_SAVE_WRITEBACK } flashcart_features_t; /** @brief Flashcart save type enumeration */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index bcab63f0..605ae419 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -232,7 +232,7 @@ static flashcart_err_t sc64_init (void) { { CFG_ID_ROM_EXTENDED_ENABLE, false }, }; - for (int i = 0; i < sizeof(default_config) / sizeof(default_config[0]); i++) { + for (unsigned int i = 0; i < sizeof(default_config) / sizeof(default_config[0]); i++) { if (sc64_ll_set_config(default_config[i].id, default_config[i].value) != SC64_OK) { return FLASHCART_ERR_INT; } @@ -256,6 +256,8 @@ static bool sc64_has_feature (flashcart_features_t feature) { case FLASHCART_FEATURE_USB: return true; case FLASHCART_FEATURE_AUTO_CIC: return true; case FLASHCART_FEATURE_AUTO_REGION: return true; + case FLASHCART_FEATURE_DIAGNOSTIC_DATA: return true; + case FLASHCART_FEATURE_SAVE_WRITEBACK: return true; default: return false; } } @@ -285,7 +287,7 @@ static flashcart_err_t sc64_load_rom (char *rom_path, flashcart_progress_callbac size_t extended_size = extended_enabled ? rom_size - MiB(64) : 0; size_t chunk_size = KiB(128); - for (int offset = 0; offset < sdram_size; offset += chunk_size) { + for (unsigned int offset = 0; offset < sdram_size; offset += chunk_size) { size_t block_size = MIN(sdram_size - offset, chunk_size); if (f_read(&fil, (void *) (ROM_ADDRESS + offset), block_size, &br) != FR_OK) { f_close(&fil); @@ -447,7 +449,7 @@ static flashcart_err_t sc64_load_64dd_ipl (char *ipl_path, flashcart_progress_ca } size_t chunk_size = KiB(128); - for (int offset = 0; offset < ipl_size; offset += chunk_size) { + for (unsigned int offset = 0; offset < ipl_size; offset += chunk_size) { size_t block_size = MIN(ipl_size - offset, chunk_size); if (f_read(&fil, (void *) (IPL_ADDRESS + offset), block_size, &br) != FR_OK) { f_close(&fil); @@ -501,7 +503,7 @@ static flashcart_err_t sc64_load_64dd_disk (char *disk_path, flashcart_disk_para { CFG_ID_BUTTON_MODE, BUTTON_MODE_DD_DISK_SWAP }, }; - for (int i = 0; i < sizeof(config) / sizeof(config[0]); i++) { + for (unsigned int i = 0; i < sizeof(config) / sizeof(config[0]); i++) { if (sc64_ll_set_config(config[i].id, config[i].value) != SC64_OK) { return FLASHCART_ERR_INT; } diff --git a/src/libs/miniz b/src/libs/miniz index 1ff82be7..35528ad7 160000 --- a/src/libs/miniz +++ b/src/libs/miniz @@ -1 +1 @@ -Subproject commit 1ff82be7d67f5c2f8b5497f538eea247861e0717 +Subproject commit 35528ad769143b9ed38a95a22d460b963e39f278 diff --git a/src/menu/actions.c b/src/menu/actions.c index 00317168..4cafbce7 100644 --- a/src/menu/actions.c +++ b/src/menu/actions.c @@ -25,8 +25,8 @@ static void actions_clear (menu_t *menu) { } static void actions_update_direction (menu_t *menu) { - joypad_8way_t held_dir; - joypad_8way_t fast_dir; + joypad_8way_t held_dir = JOYPAD_8WAY_NONE; + joypad_8way_t fast_dir = JOYPAD_8WAY_NONE; JOYPAD_PORT_FOREACH (i) { held_dir = joypad_get_direction(i, JOYPAD_2D_DPAD | JOYPAD_2D_STICK); @@ -90,7 +90,7 @@ static void actions_update_direction (menu_t *menu) { } static void actions_update_buttons (menu_t *menu) { - joypad_buttons_t pressed; + joypad_buttons_t pressed = {0}; JOYPAD_PORT_FOREACH (i) { pressed = joypad_get_buttons_pressed(i); diff --git a/src/menu/actions.h b/src/menu/actions.h index e02e35af..f10a83ce 100644 --- a/src/menu/actions.h +++ b/src/menu/actions.h @@ -10,7 +10,9 @@ #include "menu_state.h" - +/** + * @brief Initialize the actions module + */ void actions_init (void); void actions_update (menu_t *menu); diff --git a/src/menu/components.h b/src/menu/components.h index 67fde2d3..6d31a3d3 100644 --- a/src/menu/components.h +++ b/src/menu/components.h @@ -73,8 +73,8 @@ void component_background_draw (void); void component_file_list_draw (entry_t *list, int entries, int selected); typedef struct component_context_menu { - int count; - int selected; + int row_count; + int row_selected; bool hide_pending; struct component_context_menu *parent; struct component_context_menu *submenu; diff --git a/src/menu/components/boxart.c b/src/menu/components/boxart.c index 2535068c..d663230a 100644 --- a/src/menu/components/boxart.c +++ b/src/menu/components/boxart.c @@ -40,20 +40,28 @@ component_boxart_t *component_boxart_init (const char *storage_prefix, char *gam switch (current_image_view) { case IMAGE_GAMEPAK_FRONT: path_push(path, "gamepak_front.png"); + break; case IMAGE_GAMEPAK_BACK: path_push(path, "gamepak_back.png"); + break; case IMAGE_BOXART_BACK: path_push(path, "boxart_back.png"); + break; case IMAGE_BOXART_LEFT: path_push(path, "boxart_left.png"); + break; case IMAGE_BOXART_RIGHT: path_push(path, "boxart_right.png"); + break; case IMAGE_BOXART_BOTTOM: path_push(path, "boxart_bottom.png"); + break; case IMAGE_BOXART_TOP: path_push(path, "boxart_top.png"); + break; default: path_push(path, "boxart_front.png"); + break; } if (file_exists(path_get(path))) { @@ -65,12 +73,13 @@ component_boxart_t *component_boxart_init (const char *storage_prefix, char *gam } else { // compatibility mode - char file_name[8]; + char file_name[9]; // reset the directory path used for boxart. + path_free(path); 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]); + snprintf(file_name, sizeof(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))) { @@ -81,21 +90,19 @@ component_boxart_t *component_boxart_init (const char *storage_prefix, char *gam } path_pop(path); - sprintf(file_name, "%c%c%c.png", game_code[0], game_code[1], game_code[2]); + snprintf(file_name, sizeof(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; - } + 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]); + snprintf(file_name, sizeof(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) { diff --git a/src/menu/components/context_menu.c b/src/menu/components/context_menu.c index c4d0364a..abf1947e 100644 --- a/src/menu/components/context_menu.c +++ b/src/menu/components/context_menu.c @@ -13,22 +13,22 @@ static component_context_menu_t *get_current_submenu (component_context_menu_t * void component_context_menu_init (component_context_menu_t *cm) { - cm->selected = -1; - cm->count = 0; + cm->row_selected = -1; + cm->row_count = 0; cm->hide_pending = false; cm->parent = NULL; for (int i = 0; (cm->list[i].text) != NULL; i++) { - cm->count += 1; + cm->row_count += 1; } } void component_context_menu_show (component_context_menu_t *cm) { - cm->selected = 0; + cm->row_selected = 0; cm->submenu = NULL; } bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) { - if (!cm || (cm->selected < 0)) { + if (!cm || (cm->row_selected < 0)) { return false; } @@ -44,26 +44,26 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) } sound_play_effect(SFX_EXIT); } else if (menu->actions.enter) { - if (cm->list[cm->selected].submenu) { - cm->submenu = cm->list[cm->selected].submenu; + if (cm->list[cm->row_selected].submenu) { + cm->submenu = cm->list[cm->row_selected].submenu; component_context_menu_init(cm->submenu); - cm->submenu->selected = 0; + cm->submenu->row_selected = 0; cm->submenu->parent = cm; - } else if (cm->list[cm->selected].action) { - cm->list[cm->selected].action(menu, cm->list[cm->selected].arg); + } else if (cm->list[cm->row_selected].action) { + cm->list[cm->row_selected].action(menu, cm->list[cm->row_selected].arg); top->hide_pending = true; } sound_play_effect(SFX_ENTER); } else if (menu->actions.go_up) { - cm->selected -= 1; - if (cm->selected < 0) { - cm->selected = 0; + cm->row_selected -= 1; + if (cm->row_selected < 0) { + cm->row_selected = 0; } sound_play_effect(SFX_CURSOR); } else if (menu->actions.go_down) { - cm->selected += 1; - if (cm->selected >= cm->count) { - cm->selected = (cm->count - 1); + cm->row_selected += 1; + if (cm->row_selected >= cm->row_count) { + cm->row_selected = (cm->row_count - 1); } sound_play_effect(SFX_CURSOR); } @@ -72,7 +72,7 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) } void component_context_menu_draw (component_context_menu_t *cm) { - if (!cm || (cm->selected < 0)) { + if (!cm || (cm->row_selected < 0)) { return; } @@ -92,7 +92,7 @@ void component_context_menu_draw (component_context_menu_t *cm) { NULL ); - for (int i = 0; i < cm->count; i++) { + for (int i = 0; i < cm->row_count; i++) { const char *text = cm->list[i].text; rdpq_paragraph_builder_span(text, strlen(text)); if (cm->list[i + 1].text != NULL) { @@ -110,7 +110,7 @@ void component_context_menu_draw (component_context_menu_t *cm) { int highlight_x0 = DISPLAY_CENTER_X - (width / 2); int highlight_x1 = DISPLAY_CENTER_X + (width / 2); int highlight_height = (layout->bbox.y1 - layout->bbox.y0) / layout->nlines; - int highlight_y = VISIBLE_AREA_Y0 + layout->bbox.y0 + ((cm->selected) * highlight_height); + int highlight_y = VISIBLE_AREA_Y0 + layout->bbox.y0 + ((cm->row_selected) * highlight_height); component_box_draw( highlight_x0, @@ -126,6 +126,6 @@ void component_context_menu_draw (component_context_menu_t *cm) { if (top->hide_pending) { top->hide_pending = false; - top->selected = -1; + top->row_selected = -1; } } diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index e5b750ce..b313950c 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -835,6 +835,7 @@ static rom_err_t save_override (path_t *path, const char *id, int value, int def mini_t *ini = mini_try_load(path_get(overrides_path)); if (!ini) { + path_free(overrides_path); return ROM_ERR_SAVE_IO; } diff --git a/src/menu/sound.c b/src/menu/sound.c index 98d62748..ea088447 100644 --- a/src/menu/sound.c +++ b/src/menu/sound.c @@ -86,6 +86,13 @@ void sound_play_effect(sound_effect_t sfx) { void sound_deinit (void) { if (sound_initialized) { + if (sfx_enabled) { + wav64_close(&sfx_cursor); + wav64_close(&sfx_exit); + wav64_close(&sfx_setting); + wav64_close(&sfx_enter); + wav64_close(&sfx_error); + } mixer_close(); audio_close(); sound_initialized = false; @@ -93,9 +100,7 @@ void sound_deinit (void) { } void sound_poll (void) { - if (sound_initialized && audio_can_write()) { - short *audio_buffer = audio_write_begin(); - mixer_poll(audio_buffer, audio_get_buffer_length()); - audio_write_end(); + if (sound_initialized) { + mixer_try_play(); } } diff --git a/src/menu/sound.h b/src/menu/sound.h index 8752a9b9..e086a362 100644 --- a/src/menu/sound.h +++ b/src/menu/sound.h @@ -12,6 +12,9 @@ #define SOUND_MP3_PLAYER_CHANNEL (0) #define SOUND_SFX_CHANNEL (2) +/** + * @brief Enumeration of available sound effects for menu interactions. + */ typedef enum { SFX_CURSOR, SFX_ERROR, @@ -23,8 +26,22 @@ typedef enum { void sound_init_default (void); void sound_init_mp3_playback (void); + +/** + * @brief Initialize sound effects system. + */ void sound_init_sfx (void); + +/** + * @brief Enable or disable sound effects. + * @param enable True to enable sound effects, false to disable. + */ void sound_use_sfx(bool); + +/** + * @brief Play a specified sound effect. + * @param sfx The sound effect to play, as defined in sound_effect_t. + */ void sound_play_effect(sound_effect_t sfx); void sound_deinit (void); void sound_poll (void); diff --git a/src/menu/views/credits.c b/src/menu/views/credits.c index fb068e6b..1889232a 100644 --- a/src/menu/views/credits.c +++ b/src/menu/views/credits.c @@ -12,8 +12,8 @@ static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/error.c b/src/menu/views/error.c index 07eb70d4..7cb4f7d2 100644 --- a/src/menu/views/error.c +++ b/src/menu/views/error.c @@ -4,8 +4,8 @@ static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } 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/file_info.c b/src/menu/views/file_info.c index 496c07f4..9d45574b 100644 --- a/src/menu/views/file_info.c +++ b/src/menu/views/file_info.c @@ -50,8 +50,8 @@ static char *format_file_type (char *name, bool is_directory) { static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -84,7 +84,7 @@ static void draw (menu_t *menu, surface_t *d) { S_ISDIR(st.st_mode) ? "Directory" : "File", st.st_mode & S_IWUSR ? "" : "(Read only)", format_file_type(menu->browser.entry->name, S_ISDIR(st.st_mode)), - ctime(&st.st_mtim.tv_sec) + ctime(&st.st_mtime) ); component_actions_bar_text_draw( diff --git a/src/menu/views/flashcart_info.c b/src/menu/views/flashcart_info.c index 41c1f443..635ef2ca 100644 --- a/src/menu/views/flashcart_info.c +++ b/src/menu/views/flashcart_info.c @@ -1,11 +1,35 @@ #include "views.h" #include "../sound.h" +#include +static inline const char *format_boolean_type (bool bool_value) { + return bool_value ? "Supported" : "Unsupported"; +} + +static const char *format_cart_type () { + switch (cart_type) { + case CART_CI: + return "64drive"; + + case CART_EDX: + return "Series X EverDrive-64"; + + case CART_ED: + return "Series V EverDrive-64"; + + case CART_SC: + return "SummerCart64"; + + default: // Probably emulator + return "Emulator?"; + } +} + static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -18,24 +42,41 @@ static void draw (menu_t *menu, surface_t *d) { component_main_text_draw( ALIGN_CENTER, VALIGN_TOP, - "FLASHCART INFORMATION\n" + "FLASHCART INFORMATION" "\n" "\n" - "This feature is not yet supported.\n\n" ); - // FIXME: Display: - // * cart_type - // * Firmware version - // * supported features (flashcart_features_t) - - component_main_text_draw( ALIGN_LEFT, VALIGN_TOP, "\n" "\n" - ); + "Type:\n" + " %s\n\n" + "Firmware:\n" + " %s\n\n" + "Features:\n" + " Virtual 64DD: %s.\n" + " Real Time Clock: %s.\n" + " USB Debugging: %s.\n" + " Automatic CIC: %s.\n" + " Region Detection: %s.\n" + " Save Writeback: %s.\n" + " Update from menu: %s.\n" + "\n\n", + format_cart_type(), + "Not Available", // TODO get cart firmware version(s). + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_64DD)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_RTC)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_USB)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_AUTO_CIC)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_AUTO_REGION)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_SAVE_WRITEBACK)), + format_boolean_type(flashcart_has_feature(FLASHCART_FEATURE_BIOS_UPDATE_FROM_MENU)) + //TODO: display the battery and temperature information (if available). + //format_diagnostic_data(flashcart_has_feature(FLASHCART_FEATURE_DIAGNOSTIC_DATA)) + ); component_actions_bar_text_draw( ALIGN_LEFT, VALIGN_TOP, diff --git a/src/menu/views/load_disk.c b/src/menu/views/load_disk.c index 39957fcf..be95010a 100644 --- a/src/menu/views/load_disk.c +++ b/src/menu/views/load_disk.c @@ -38,8 +38,8 @@ static void process (menu_t *menu) { load_rom = true; sound_play_effect(SFX_SETTING); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -94,7 +94,9 @@ static void draw (menu_t *menu, surface_t *d) { ); } - component_boxart_draw(boxart); + if (boxart != NULL) { + component_boxart_draw(boxart); + } } rdpq_detach_show(); diff --git a/src/menu/views/load_emulator.c b/src/menu/views/load_emulator.c index 589a6a59..9cfaeb48 100644 --- a/src/menu/views/load_emulator.c +++ b/src/menu/views/load_emulator.c @@ -36,8 +36,8 @@ static void process (menu_t *menu) { if (menu->actions.enter) { load_pending = true; } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index 36933b92..18acd7e6 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -198,8 +198,8 @@ static void process (menu_t *menu) { if (menu->actions.enter) { load_pending = true; } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (menu->actions.options) { component_context_menu_show(&options_context_menu); sound_play_effect(SFX_SETTING); @@ -262,7 +262,9 @@ static void draw (menu_t *menu, surface_t *d) { "R: Options" ); - component_boxart_draw(boxart); + if (boxart != NULL) { + component_boxart_draw(boxart); + } if (show_extra_info_message) { component_messagebox_draw( @@ -335,6 +337,7 @@ static void load (menu_t *menu) { static void deinit (void) { component_boxart_free(boxart); + boxart = NULL; } diff --git a/src/menu/views/music_player.c b/src/menu/views/music_player.c index 4de00756..c540bfab 100644 --- a/src/menu/views/music_player.c +++ b/src/menu/views/music_player.c @@ -41,8 +41,8 @@ static void process (menu_t *menu) { if (err != MP3PLAYER_OK) { menu_show_error(menu, convert_error_message(err)); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (menu->actions.enter) { err = mp3player_toggle(); if (err != MP3PLAYER_OK) { diff --git a/src/menu/views/rtc.c b/src/menu/views/rtc.c index ae56fd8b..6be481a3 100644 --- a/src/menu/views/rtc.c +++ b/src/menu/views/rtc.c @@ -18,8 +18,8 @@ static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -36,7 +36,7 @@ static void draw (menu_t *menu, surface_t *d) { "\n" "\n" "To set the date and time, please use the PC terminal\n" - "application and set via USB or a game that uses it.\n\n" + "application and set via USB,\n or a N64 game with RTC support.\n\n" "Current date & time: %s\n", menu->current_time >= 0 ? ctime(&menu->current_time) : "Unknown\n" ); diff --git a/src/menu/views/settings_editor.c b/src/menu/views/settings_editor.c index 55feffea..64bed3b9 100644 --- a/src/menu/views/settings_editor.c +++ b/src/menu/views/settings_editor.c @@ -12,36 +12,36 @@ static const char *format_switch (bool state) { } static void set_pal60_type (menu_t *menu, void *arg) { - menu->settings.pal60_enabled = (bool) (arg); + menu->settings.pal60_enabled = (bool)(uintptr_t)(arg); settings_save(&menu->settings); } static void set_protected_entries_type (menu_t *menu, void *arg) { - menu->settings.show_protected_entries = (bool) (arg); + menu->settings.show_protected_entries = (bool)(uintptr_t)(arg); settings_save(&menu->settings); menu->browser.reload = true; } static void set_use_saves_folder_type (menu_t *menu, void *arg) { - menu->settings.use_saves_folder = (bool) (arg); + menu->settings.use_saves_folder = (bool)(uintptr_t)(arg); settings_save(&menu->settings); } static void set_sound_enabled_type (menu_t *menu, void *arg) { - menu->settings.sound_enabled = (bool) (arg); + menu->settings.sound_enabled = (bool)(uintptr_t)(arg); sound_use_sfx(menu->settings.sound_enabled); settings_save(&menu->settings); } #ifdef BETA_SETTINGS static void set_bgm_enabled_type (menu_t *menu, void *arg) { - menu->settings.bgm_enabled = (bool) (arg); + menu->settings.bgm_enabled = (bool)(uintptr_t)(arg); settings_save(&menu->settings); } static void set_rumble_enabled_type (menu_t *menu, void *arg) { - menu->settings.rumble_enabled = (bool) (arg); + menu->settings.rumble_enabled = (bool)(uintptr_t)(arg); settings_save(&menu->settings); } @@ -53,39 +53,39 @@ static void set_rumble_enabled_type (menu_t *menu, void *arg) { static component_context_menu_t set_pal60_type_context_menu = { .list = { - {.text = "On", .action = set_pal60_type, .arg = (void *) (true) }, + {.text = "On", .action = set_pal60_type, .arg = (void *)(uintptr_t)(true) }, {.text = "Off", .action = set_pal60_type, .arg = (void *) (false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; static component_context_menu_t set_protected_entries_type_context_menu = { .list = { - {.text = "On", .action = set_protected_entries_type, .arg = (void *) (true) }, - {.text = "Off", .action = set_protected_entries_type, .arg = (void *) (false) }, + {.text = "On", .action = set_protected_entries_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_protected_entries_type, .arg = (void *)(uintptr_t)(false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; static component_context_menu_t set_sound_enabled_type_context_menu = { .list = { - {.text = "On", .action = set_sound_enabled_type, .arg = (void *) (true) }, - {.text = "Off", .action = set_sound_enabled_type, .arg = (void *) (false) }, + {.text = "On", .action = set_sound_enabled_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_sound_enabled_type, .arg = (void *)(uintptr_t)(false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; static component_context_menu_t set_use_saves_folder_type_context_menu = { .list = { - {.text = "On", .action = set_use_saves_folder_type, .arg = (void *) (true) }, - {.text = "Off", .action = set_use_saves_folder_type, .arg = (void *) (false) }, + {.text = "On", .action = set_use_saves_folder_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_use_saves_folder_type, .arg = (void *)(uintptr_t)(false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; #ifdef BETA_SETTINGS static component_context_menu_t set_bgm_enabled_type_context_menu = { .list = { - {.text = "On", .action = set_bgm_enabled_type, .arg = (void *) (true) }, - {.text = "Off", .action = set_bgm_enabled_type, .arg = (void *) (false) }, + {.text = "On", .action = set_bgm_enabled_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_bgm_enabled_type, .arg = (void *)(uintptr_t)(false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; static component_context_menu_t set_rumble_enabled_type_context_menu = { .list = { - {.text = "On", .action = set_rumble_enabled_type, .arg = (void *) (true) }, - {.text = "Off", .action = set_rumble_enabled_type, .arg = (void *) (false) }, + {.text = "On", .action = set_rumble_enabled_type, .arg = (void *)(uintptr_t)(true) }, + {.text = "Off", .action = set_rumble_enabled_type, .arg = (void *)(uintptr_t)(false) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; #endif @@ -114,8 +114,8 @@ static void process (menu_t *menu) { component_context_menu_show(&options_context_menu); sound_play_effect(SFX_SETTING); } else if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } @@ -145,8 +145,9 @@ static void draw (menu_t *menu, surface_t *d) { " Background Music : %s\n" " Rumble Feedback : %s\n" #endif - "Note: Certain settings have the following caveats:\n\n" - "* Requires a flashcart reboot.\n", + "\n\n" + "Note: Certain settings have the following caveats:\n" + "* Requires rebooting the N64 Console.\n", menu->settings.default_directory, format_switch(menu->settings.pal60_enabled), format_switch(menu->settings.show_protected_entries), diff --git a/src/menu/views/system_info.c b/src/menu/views/system_info.c index 74ed4cbd..2dea476d 100644 --- a/src/menu/views/system_info.c +++ b/src/menu/views/system_info.c @@ -28,8 +28,8 @@ static void process (menu_t *menu) { } if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } } diff --git a/src/menu/views/text_viewer.c b/src/menu/views/text_viewer.c index cf8b505f..0339ba37 100644 --- a/src/menu/views/text_viewer.c +++ b/src/menu/views/text_viewer.c @@ -55,8 +55,8 @@ static void perform_vertical_scroll (int lines) { static void process (menu_t *menu) { if (menu->actions.back) { - menu->next_mode = MENU_MODE_BROWSER; sound_play_effect(SFX_EXIT); + menu->next_mode = MENU_MODE_BROWSER; } else if (text) { if (menu->actions.go_up) { perform_vertical_scroll(menu->actions.go_fast ? -10 : -1);