From 80eb7bbd9c01a736b44751b7e6f0cccdb5c80083 Mon Sep 17 00:00:00 2001 From: Mateusz Faderewski Date: Wed, 17 Jan 2024 15:43:02 +0100 Subject: [PATCH 1/5] Added CIC selection menu + minor fixes and code cleanup --- Makefile | 8 +- libdragon | 2 +- src/boot/cic.c | 4 +- src/boot/cic.h | 2 +- src/flashcart/64drive/64drive.c | 2 +- src/flashcart/sc64/sc64.c | 4 +- src/menu/components.h | 3 +- src/menu/components/context_menu.c | 2 +- src/menu/menu.c | 62 ++++++---- src/menu/menu_state.h | 1 - src/menu/mp3_player.c | 6 +- src/menu/png_decoder.c | 1 + src/menu/rom_info.c | 179 ++++++++++++++++++----------- src/menu/rom_info.h | 87 ++++++++++---- src/menu/sound.c | 2 +- src/menu/usb_comm.c | 2 + src/menu/views/browser.c | 68 +++++------ src/menu/views/credits.c | 12 +- src/menu/views/load_disk.c | 18 ++- src/menu/views/load_rom.c | 144 +++++++++++++---------- src/menu/views/settings_editor.c | 23 ++-- src/menu/views/system_info.c | 41 +++---- src/menu/views/views.h | 18 +-- 23 files changed, 417 insertions(+), 274 deletions(-) diff --git a/Makefile b/Makefile index 2cc28f62..db6493d9 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,8 @@ FILESYSTEM_DIR = filesystem BUILD_DIR = build OUTPUT_DIR = output -FLAGS += -DMENU_VERSION=\"0.0.1.$(shell date +%Y-%m-%dT%H:%M:%SZ).ALPHA\" +MENU_VERSION ?= "Rolling release" +BUILD_TIMESTAMP = "$(shell TZ='UTC' date "+%Y-%m-%d %H:%M:%S %:z")" include $(N64_INST)/include/n64.mk @@ -88,6 +89,9 @@ $(FILESYSTEM_DIR)/%.font64: $(ASSETS_DIR)/%.ttf $(BUILD_DIR)/$(PROJECT_NAME).dfs: $(FILESYSTEM) +$(BUILD_DIR)/menu/views/credits.o: .FORCE +$(BUILD_DIR)/menu/views/credits.o: FLAGS+=-DMENU_VERSION=\"$(MENU_VERSION)\" -DBUILD_TIMESTAMP=\"$(BUILD_TIMESTAMP)\" + $(BUILD_DIR)/$(PROJECT_NAME).elf: $(OBJS) disassembly: $(BUILD_DIR)/$(PROJECT_NAME).elf @@ -144,4 +148,6 @@ endif # test: # TODO: run tests +.FORCE: + -include $(DEPS) diff --git a/libdragon b/libdragon index 6323128d..185c4a34 160000 --- a/libdragon +++ b/libdragon @@ -1 +1 @@ -Subproject commit 6323128d72fdf32dfaa134f40191ba72e5527076 +Subproject commit 185c4a34f265c90d027f4054024cff1675529d7f diff --git a/src/boot/cic.c b/src/boot/cic.c index 58f03fbc..990e95ca 100644 --- a/src/boot/cic.c +++ b/src/boot/cic.c @@ -102,7 +102,7 @@ cic_type_t cic_detect (uint8_t *ipl3) { switch (cic_calculate_ipl3_checksum(ipl3, 0x3F)) { case 0x45CC73EE317AULL: return CIC_6101; // 6101 case 0x44160EC5D9AFULL: return CIC_7102; // 7102 - case 0xA536C0F1D859ULL: return CIC_6102_7101; // 6102 / 7101 + case 0xA536C0F1D859ULL: return CIC_x102; // 6102 / 7101 } switch (cic_calculate_ipl3_checksum(ipl3, 0x78)) { case 0x586FD4709867ULL: return CIC_x103; // 6103 / 7103 @@ -133,7 +133,7 @@ uint8_t cic_get_seed (cic_type_t cic_type) { case CIC_5167: return 0xDD; case CIC_6101: return 0x3F; case CIC_7102: return 0x3F; - case CIC_6102_7101: return 0x3F; + case CIC_x102: return 0x3F; case CIC_x103: return 0x78; case CIC_x105: return 0x91; case CIC_x106: return 0x85; diff --git a/src/boot/cic.h b/src/boot/cic.h index 4f97c6c4..3de811bb 100644 --- a/src/boot/cic.h +++ b/src/boot/cic.h @@ -13,7 +13,7 @@ typedef enum { CIC_5167, CIC_6101, CIC_7102, - CIC_6102_7101, + CIC_x102, CIC_x103, CIC_x105, CIC_x106, diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index 6bcee6cb..b2ed3b36 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -96,7 +96,7 @@ static flashcart_err_t d64_load_rom (char *rom_path, flashcart_progress_callback size_t sdram_size = MiB(64); - size_t chunk_size = MiB(1); + size_t chunk_size = KiB(128); for (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) { diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index a0878c9d..58f4c450 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -288,7 +288,7 @@ static flashcart_err_t sc64_load_rom (char *rom_path, flashcart_progress_callbac size_t shadow_size = shadow_enabled ? MIN(rom_size - sdram_size, KiB(128)) : 0; size_t extended_size = extended_enabled ? rom_size - MiB(64) : 0; - size_t chunk_size = MiB(1); + size_t chunk_size = KiB(128); for (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) { @@ -450,7 +450,7 @@ static flashcart_err_t sc64_load_64dd_ipl (char *ipl_path, flashcart_progress_ca return FLASHCART_ERR_LOAD; } - size_t chunk_size = KiB(256); + size_t chunk_size = KiB(128); for (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) { diff --git a/src/menu/components.h b/src/menu/components.h index 127c1d7b..a8cecb51 100644 --- a/src/menu/components.h +++ b/src/menu/components.h @@ -45,7 +45,8 @@ typedef struct component_context_menu { struct component_context_menu *submenu; struct { const char *text; - void (*action) (menu_t *menu); + void (*action) (menu_t *menu, void *arg); + void *arg; struct component_context_menu *submenu; } list[]; } component_context_menu_t; diff --git a/src/menu/components/context_menu.c b/src/menu/components/context_menu.c index 82b3daa0..f2e32c42 100644 --- a/src/menu/components/context_menu.c +++ b/src/menu/components/context_menu.c @@ -48,7 +48,7 @@ bool component_context_menu_process (menu_t *menu, component_context_menu_t *cm) cm->submenu->selected = 0; cm->submenu->parent = cm; } else if (cm->list[cm->selected].action) { - cm->list[cm->selected].action(menu); + cm->list[cm->selected].action(menu, cm->list[cm->selected].arg); top->hide_pending = true; } } else if (menu->actions.go_up) { diff --git a/src/menu/menu.c b/src/menu/menu.c index 7cd3758a..06e9ef2d 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -20,6 +20,7 @@ #include "views/views.h" +#define MENU_DIRECTORY "sd:/menu" #define CACHE_DIRECTORY "sd:/menu/cache" #define BACKGROUND_CACHE "sd:/menu/cache/background.data" @@ -77,6 +78,8 @@ static void menu_init (boot_params_t *boot_params) { menu->error_message = NULL; + directory_create(MENU_DIRECTORY); + settings_load(&menu->settings); directory_create(CACHE_DIRECTORY); @@ -133,30 +136,39 @@ static void menu_deinit (menu_t *menu) { display_close(); } - -// NOTE: Keep this array in sync with menu_mode_t -static struct views_s { +typedef const struct { + menu_mode_t id; void (*init) (menu_t *menu); void (*show) (menu_t *menu, surface_t *display); -} views[__MENU_MODE_COUNT] = { - { NULL, NULL }, // MENU_MODE_NONE - { view_startup_init, view_startup_display }, // MENU_MODE_STARTUP - { view_browser_init, view_browser_display }, // MENU_MODE_BROWSER - { view_file_info_init, view_file_info_display }, // MENU_MODE_FILE_INFO - { view_system_info_init, view_system_info_display }, // MENU_MODE_SYSTEM_INFO - { view_image_viewer_init, view_image_viewer_display }, // MENU_MODE_IMAGE_VIEWER - { view_music_player_init, view_music_player_display }, // MENU_MODE_MUSIC_PLAYER - { view_credits_init, view_credits_display }, // MENU_MODE_CREDITS - { view_settings_init, view_settings_display }, // MENU_MODE_SETTINGS_EDITOR - { view_rtc_init, view_rtc_display }, // MENU_MODE_RTC - { view_load_rom_init, view_load_rom_display }, // MENU_MODE_LOAD_ROM - { view_load_disk_init, view_load_disk_display }, // MENU_MODE_LOAD_DISK - { view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_LOAD_EMULATOR - { view_error_init, view_error_display }, // MENU_MODE_ERROR - { view_fault_init, view_fault_display }, // MENU_MODE_FAULT - { NULL, NULL }, // MENU_MODE_BOOT +} view_t; + +static view_t menu_views[] = { + { MENU_MODE_STARTUP, view_startup_init, view_startup_display }, + { MENU_MODE_BROWSER, view_browser_init, view_browser_display }, + { MENU_MODE_FILE_INFO, view_file_info_init, view_file_info_display }, + { MENU_MODE_SYSTEM_INFO, view_system_info_init, view_system_info_display }, + { MENU_MODE_IMAGE_VIEWER, view_image_viewer_init, view_image_viewer_display }, + { MENU_MODE_MUSIC_PLAYER, view_music_player_init, view_music_player_display }, + { MENU_MODE_CREDITS, view_credits_init, view_credits_display }, + { MENU_MODE_SETTINGS_EDITOR, view_settings_init, view_settings_display }, + { MENU_MODE_RTC, view_rtc_init, view_rtc_display }, + { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, + { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, + { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, + { MENU_MODE_ERROR, view_error_init, view_error_display }, + { MENU_MODE_FAULT, view_fault_init, view_fault_display }, }; +static view_t *menu_get_view (menu_mode_t id) { + for (int i = 0; i < sizeof(menu_views) / sizeof(view_t); i++) { + if (menu_views[i].id == id) { + return &menu_views[i]; + } + } + return NULL; +} + + void menu_run (boot_params_t *boot_params) { menu_init(boot_params); @@ -168,8 +180,9 @@ void menu_run (boot_params_t *boot_params) { actions_update(menu); - if (views[menu->mode].show) { - views[menu->mode].show(menu, display); + view_t *view = menu_get_view(menu->mode); + if (view && view->show) { + view->show(menu, display); } else { rdpq_attach_clear(display, NULL); rdpq_detach_wait(); @@ -183,8 +196,9 @@ void menu_run (boot_params_t *boot_params) { while (menu->mode != menu->next_mode) { menu->mode = menu->next_mode; - if (views[menu->mode].init) { - views[menu->mode].init(menu); + view_t *next_view = menu_get_view(menu->next_mode); + if (next_view && next_view->init) { + next_view->init(menu); } } diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index d29573d4..9fcee137 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -39,7 +39,6 @@ typedef enum { MENU_MODE_ERROR, MENU_MODE_FAULT, MENU_MODE_BOOT, - __MENU_MODE_COUNT, } menu_mode_t; /** @brief File entry type enumeration */ diff --git a/src/menu/mp3_player.c b/src/menu/mp3_player.c index 3dfbd7da..87109a3e 100644 --- a/src/menu/mp3_player.c +++ b/src/menu/mp3_player.c @@ -27,7 +27,7 @@ typedef struct { mp3dec_t dec; mp3dec_frame_info_t info; - uint8_t buffer[MAX_FREE_FORMAT_FRAME_SIZE]; + uint8_t buffer[16 * 1024]; uint8_t *buffer_ptr; size_t buffer_left; @@ -54,6 +54,10 @@ static void mp3player_fill_buffer (void) { return; } + if (p->buffer_left >= ALIGN(MAX_FREE_FORMAT_FRAME_SIZE, FS_SECTOR_SIZE)) { + return; + } + if ((p->buffer_ptr != p->buffer) && (p->buffer_left > 0)) { memmove(p->buffer, p->buffer_ptr, p->buffer_left); p->buffer_ptr = p->buffer; diff --git a/src/menu/png_decoder.c b/src/menu/png_decoder.c index 951057b6..54d185d3 100644 --- a/src/menu/png_decoder.c +++ b/src/menu/png_decoder.c @@ -4,6 +4,7 @@ #include "png_decoder.h" #include "utils/fs.h" + /** @brief PNG File Information Structure. */ typedef struct { FIL fil; diff --git a/src/menu/rom_info.c b/src/menu/rom_info.c index 8d8f1f49..6a2223c5 100644 --- a/src/menu/rom_info.c +++ b/src/menu/rom_info.c @@ -3,6 +3,7 @@ #include #include +#include "boot/cic.h" #include "rom_info.h" #include "utils/fs.h" @@ -16,6 +17,7 @@ #define CLOCK_RATE_DEFAULT (0x0000000F) + /** @brief ROM File Information Structure. */ typedef struct __attribute__((packed)) { uint32_t pi_dom1_config; @@ -652,15 +654,34 @@ static match_t find_rom_in_database (rom_header_t *rom_header) { return *match; } -static uint32_t fix_boot_address (cic_type_t cic_type, uint32_t boot_address) { +static rom_cic_type_t detect_cic_type (uint8_t *ipl3) { + switch (cic_detect(ipl3)) { + case CIC_5101: return ROM_CIC_TYPE_5101; + case CIC_5167: return ROM_CIC_TYPE_5167; + case CIC_6101: return ROM_CIC_TYPE_6101; + case CIC_7102: return ROM_CIC_TYPE_7102; + case CIC_x102: return ROM_CIC_TYPE_x102; + case CIC_x103: return ROM_CIC_TYPE_x103; + case CIC_x105: return ROM_CIC_TYPE_x105; + case CIC_x106: return ROM_CIC_TYPE_x106; + case CIC_8301: return ROM_CIC_TYPE_8301; + case CIC_8302: return ROM_CIC_TYPE_8302; + case CIC_8303: return ROM_CIC_TYPE_8303; + case CIC_8401: return ROM_CIC_TYPE_8401; + case CIC_8501: return ROM_CIC_TYPE_8501; + default: return ROM_CIC_TYPE_UNKNOWN; + } +} + +static uint32_t fix_boot_address (rom_cic_type_t cic_type, uint32_t boot_address) { switch (cic_type) { - case CIC_x103: return (boot_address - 0x100000); - case CIC_x106: return (boot_address - 0x200000); + case ROM_CIC_TYPE_x103: return (boot_address - 0x100000); + case ROM_CIC_TYPE_x106: return (boot_address - 0x200000); default: return boot_address; } } -static rom_tv_type_t determine_tv_type (destination_type_t rom_destination_code) { +static rom_tv_type_t determine_tv_type (rom_destination_type_t rom_destination_code) { // check the market type from the ROM destination_code and return best guess! switch (rom_destination_code) { case MARKET_NORTH_AMERICA: @@ -695,7 +716,7 @@ static rom_tv_type_t determine_tv_type (destination_type_t rom_destination_code) } static void extract_rom_info (match_t *match, rom_header_t *rom_header, rom_info_t *rom_info) { - rom_info->cic_type = cic_detect(rom_header->ipl3); + rom_info->cic_type = detect_cic_type(rom_header->ipl3); if (match->type == MATCH_TYPE_HOMEBREW_HEADER) { if (rom_header->version & (1 << 0)) { @@ -746,63 +767,72 @@ static void extract_rom_info (match_t *match, rom_header_t *rom_header, rom_info } static void load_overrides (path_t *path, rom_info_t *rom_info) { + path_t *overrides_path = path_clone(path); + + path_ext_replace(overrides_path, "ini"); + + mini_t *ini = mini_load(path_get(overrides_path)); + + rom_info->override.cic = false; rom_info->override.save = false; rom_info->override.tv = false; - path_t *overrides_path = path_clone(path); + if (ini) { + rom_info->override.cic_type = mini_get_int(ini, NULL, "cic_type", ROM_CIC_TYPE_AUTOMATIC); + if (rom_info->override.cic_type != ROM_CIC_TYPE_AUTOMATIC) { + rom_info->override.cic = true; + } - path_ext_replace(overrides_path, "ini"); + rom_info->override.save_type = mini_get_int(ini, NULL, "save_type", SAVE_TYPE_AUTOMATIC); + if (rom_info->override.save_type != SAVE_TYPE_AUTOMATIC) { + rom_info->override.save = true; + } - if (!file_exists(path_get(overrides_path))) { - path_free(overrides_path); - return; + rom_info->override.tv_type = mini_get_int(ini, NULL, "tv_type", ROM_TV_TYPE_AUTOMATIC); + if (rom_info->override.tv_type != ROM_TV_TYPE_AUTOMATIC) { + rom_info->override.tv = true; + } + + mini_free(ini); } - mini_t *ini = mini_try_load(path_get(overrides_path)); - - rom_info->override.save_type = mini_get_int(ini, NULL, "save_type", SAVE_TYPE_AUTOMATIC); - if (rom_info->override.save_type != SAVE_TYPE_AUTOMATIC) { - rom_info->override.save = true; - } - - rom_info->override.tv_type = mini_get_int(ini, NULL, "tv_type", ROM_TV_TYPE_AUTOMATIC); - if (rom_info->override.tv_type != ROM_TV_TYPE_AUTOMATIC) { - rom_info->override.tv = true; - } - - mini_free(ini); - path_free(overrides_path); } - -rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type) { +static rom_err_t save_override (path_t *path, const char *id, int value, int default_value) { path_t *overrides_path = path_clone(path); path_ext_replace(overrides_path, "ini"); mini_t *ini = mini_try_load(path_get(overrides_path)); - rom_info->override.save_type = save_type; - - if (rom_info->override.save_type == SAVE_TYPE_AUTOMATIC) { - rom_info->override.save = false; - mini_delete_value(ini, NULL, "save_type"); - } else { - rom_info->override.save = true; - mini_set_int(ini, NULL, "save_type", rom_info->override.save_type); + if (!ini) { + return ROM_ERR_IO; } - bool empty_override_file = mini_empty(ini); + if (value == default_value) { + mini_delete_value(ini, NULL, id); + } else { + mini_set_int(ini, NULL, id, value); + } - if (!empty_override_file) { - mini_save(ini, MINI_FLAGS_NONE); + bool empty = mini_empty(ini); + + if (!empty) { + if (mini_save(ini, MINI_FLAGS_NONE) != MINI_OK) { + path_free(overrides_path); + mini_free(ini); + return ROM_ERR_IO; + } } mini_free(ini); - if (empty_override_file) { - file_delete(path_get(overrides_path)); + if (empty) { + if (file_delete(path_get(overrides_path))) { + path_free(overrides_path); + return ROM_ERR_IO; + } } path_free(overrides_path); @@ -810,38 +840,45 @@ rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_s return ROM_OK; } -rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type) { - path_t *overrides_path = path_clone(path); - path_ext_replace(overrides_path, "ini"); - - mini_t *ini = mini_try_load(path_get(overrides_path)); - - rom_info->override.tv_type = tv_type; - - if (rom_info->override.tv_type == ROM_TV_TYPE_AUTOMATIC) { - rom_info->override.tv = false; - mini_delete_value(ini, NULL, "tv_type"); +rom_cic_type_t rom_info_get_cic_type (rom_info_t *rom_info) { + if (rom_info->override.cic) { + return rom_info->override.cic_type; } else { - rom_info->override.tv = true; - mini_set_int(ini, NULL, "tv_type", rom_info->override.tv_type); + return rom_info->cic_type; + } +} + +bool rom_info_get_cic_seed (rom_info_t *rom_info, uint8_t *seed) { + cic_type_t cic_type; + + switch (rom_info_get_cic_type(rom_info)) { + case ROM_CIC_TYPE_5101: cic_type = CIC_5101; break; + case ROM_CIC_TYPE_5167: cic_type = CIC_5167; break; + case ROM_CIC_TYPE_6101: cic_type = CIC_6101; break; + case ROM_CIC_TYPE_7102: cic_type = CIC_7102; break; + case ROM_CIC_TYPE_x102: cic_type = CIC_x102; break; + case ROM_CIC_TYPE_x103: cic_type = CIC_x103; break; + case ROM_CIC_TYPE_x105: cic_type = CIC_x105; break; + case ROM_CIC_TYPE_x106: cic_type = CIC_x106; break; + case ROM_CIC_TYPE_8301: cic_type = CIC_8301; break; + case ROM_CIC_TYPE_8302: cic_type = CIC_8302; break; + case ROM_CIC_TYPE_8303: cic_type = CIC_8303; break; + case ROM_CIC_TYPE_8401: cic_type = CIC_8401; break; + case ROM_CIC_TYPE_8501: cic_type = CIC_8501; break; + default: cic_type = CIC_UNKNOWN; break; } - bool empty_override_file = mini_empty(ini); + *seed = cic_get_seed(cic_type); - if (!empty_override_file) { - mini_save(ini, MINI_FLAGS_NONE); - } + return (!rom_info->override.cic); +} - mini_free(ini); +rom_err_t rom_info_override_cic_type (path_t *path, rom_info_t *rom_info, rom_cic_type_t cic_type) { + rom_info->override.cic = (cic_type != ROM_CIC_TYPE_AUTOMATIC); + rom_info->override.cic_type = cic_type; - if (empty_override_file) { - file_delete(path_get(overrides_path)); - } - - path_free(overrides_path); - - return ROM_OK; + return save_override(path, "cic_type", rom_info->override.cic_type, ROM_CIC_TYPE_AUTOMATIC); } rom_save_type_t rom_info_get_save_type (rom_info_t *rom_info) { @@ -852,6 +889,13 @@ rom_save_type_t rom_info_get_save_type (rom_info_t *rom_info) { } } +rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type) { + rom_info->override.save = (save_type != SAVE_TYPE_AUTOMATIC); + rom_info->override.save_type = save_type; + + return save_override(path, "save_type", rom_info->override.save_type, SAVE_TYPE_AUTOMATIC); +} + rom_tv_type_t rom_info_get_tv_type (rom_info_t *rom_info) { if (rom_info->override.tv) { return rom_info->override.tv_type; @@ -860,6 +904,13 @@ rom_tv_type_t rom_info_get_tv_type (rom_info_t *rom_info) { } } +rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type) { + rom_info->override.tv = (tv_type != ROM_TV_TYPE_AUTOMATIC); + rom_info->override.tv_type = tv_type; + + return save_override(path, "tv_type", rom_info->override.tv_type, ROM_TV_TYPE_AUTOMATIC); +} + rom_err_t rom_info_load (path_t *path, rom_info_t *rom_info) { FIL fil; UINT br; diff --git a/src/menu/rom_info.h b/src/menu/rom_info.h index a4088c64..cb241a2e 100644 --- a/src/menu/rom_info.h +++ b/src/menu/rom_info.h @@ -1,7 +1,7 @@ /** * @file rom_info.h * @brief N64 ROM Database. - * @note Only works with N64 ROM's by checking the first 1024 bytes of the file. + * @note Only works with N64 ROM's by checking the first 4096 bytes of the file. * @ingroup menu */ @@ -12,7 +12,6 @@ #include #include -#include "boot/cic.h" #include "path.h" @@ -31,7 +30,7 @@ typedef enum { ENDIANNESS_LITTLE, /** @brief Is Byte Swapped Endian. */ ENDIANNESS_BYTE_SWAP, -} endianness_t; +} rom_endianness_t; /** @brief ROM media type enumeration. */ typedef enum { @@ -45,7 +44,7 @@ typedef enum { N64_DISK_EXPANDABLE = 'E', /** @brief Is an Aleck64 program. */ N64_ALECK64 = 'Z' -} category_type_t; +} rom_category_type_t; /** @brief ROM market region & language type enumeration. */ typedef enum { @@ -89,27 +88,46 @@ typedef enum { MARKET_OTHER_Y = 'Y', // many EU ROM's uses this. /** @brief The ROM is designed for an undefined region and TBD language(s). */ MARKET_OTHER_Z = 'Z' // no known ROM's use this. -} destination_type_t; +} rom_destination_type_t; + +/** @brief ROM CIC type enumeration. */ +typedef enum { + ROM_CIC_TYPE_UNKNOWN = 0, // No known CIC type detected + ROM_CIC_TYPE_5101 = 5101, // Aleck64 CIC-5101 + ROM_CIC_TYPE_5167 = 5167, // 64DD ROM conversion CIC-5167 + ROM_CIC_TYPE_6101 = 6101, // NTSC CIC-6101 + ROM_CIC_TYPE_7102 = 7102, // PAL CIC-7102 + ROM_CIC_TYPE_x102 = 6102, // NTSC CIC-6102 / PAL CIC-7101 + ROM_CIC_TYPE_x103 = 6103, // NTSC CIC-6103 / PAL CIC-7103 + ROM_CIC_TYPE_x105 = 6105, // NTSC CIC-6105 / PAL CIC-7105 + ROM_CIC_TYPE_x106 = 6106, // NTSC CIC-6106 / PAL CIC-7106 + ROM_CIC_TYPE_8301 = 8301, // NDDJ0 64DD IPL + ROM_CIC_TYPE_8302 = 8302, // NDDJ1 64DD IPL + ROM_CIC_TYPE_8303 = 8303, // NDDJ2 64DD IPL + ROM_CIC_TYPE_8401 = 8401, // NDXJ0 64DD IPL + ROM_CIC_TYPE_8501 = 8501, // NDDE0 64DD IPL + ROM_CIC_TYPE_AUTOMATIC = -1, // Guess CIC from IPL3 +} rom_cic_type_t; /** @brief ROM save type enumeration. */ typedef enum { /** @brief There is no expected save type. */ - SAVE_TYPE_NONE, - SAVE_TYPE_EEPROM_4K, - SAVE_TYPE_EEPROM_16K, - SAVE_TYPE_SRAM, - SAVE_TYPE_SRAM_BANKED, - SAVE_TYPE_SRAM_128K, - SAVE_TYPE_FLASHRAM, - SAVE_TYPE_FLASHRAM_PKST2, + SAVE_TYPE_NONE = 0, + SAVE_TYPE_EEPROM_4K = 1, + SAVE_TYPE_EEPROM_16K = 2, + SAVE_TYPE_SRAM = 3, + SAVE_TYPE_SRAM_BANKED = 4, + SAVE_TYPE_SRAM_128K = 5, + SAVE_TYPE_FLASHRAM = 6, + SAVE_TYPE_FLASHRAM_PKST2 = 7, SAVE_TYPE_AUTOMATIC = -1, } rom_save_type_t; typedef enum { - ROM_TV_TYPE_PAL, - ROM_TV_TYPE_NTSC, - ROM_TV_TYPE_MPAL, - ROM_TV_TYPE_UNKNOWN, + ROM_TV_TYPE_PAL = 0, + ROM_TV_TYPE_NTSC = 1, + ROM_TV_TYPE_MPAL = 2, + ROM_TV_TYPE_UNKNOWN = 3, ROM_TV_TYPE_AUTOMATIC = -1, } rom_tv_type_t; @@ -129,49 +147,62 @@ typedef enum { /** @brief The ROM is faulty when using 8MB of memory. */ EXPANSION_PAK_FAULTY, -} expansion_pak_t; +} rom_expansion_pak_t; /** @brief ROM Information Structure. */ typedef struct { /** @brief The file endian. */ - endianness_t endianness; + rom_endianness_t endianness; + /** @brief The clock rate defined in the ROM's header. */ float clock_rate; + /** @brief The boot address defined in the ROM's header. */ uint32_t boot_address; + struct { /** @brief The SDK version defined in the ROM's header. */ uint8_t version; /** @brief The SDK revision defined in the ROM's header. */ char revision; } libultra; + /** @brief The check code defined in the ROM's header. */ uint64_t check_code; + /** @brief The title defined in the ROM's header. */ char title[20]; + union { /** @brief The game code defined in the ROM's header. */ char game_code[4]; struct { /** @brief The game media type. */ - category_type_t category_code : 8; + rom_category_type_t category_code : 8; /** @brief The game unique identifier. */ char unique_code[2]; /** @brief The game region and or market. */ - destination_type_t destination_code : 8; + rom_destination_type_t destination_code : 8; }; }; + /** @brief The ROM version defined in the ROM's header. */ uint8_t version; - cic_type_t cic_type; + /** @brief The CIC type required by the ROM. */ + rom_cic_type_t cic_type; /** @brief The save type required by the ROM. */ rom_save_type_t save_type; + /** @brief The TV type required by the ROM. */ rom_tv_type_t tv_type; + /** @brief Overrides of auto-detected CIC/save/TV types. */ struct { + bool cic; + rom_cic_type_t cic_type; + bool save; rom_save_type_t save_type; @@ -188,15 +219,21 @@ typedef struct { bool real_time_clock; bool disk_conversion; bool combo_rom_disk_game; - expansion_pak_t expansion_pak; + rom_expansion_pak_t expansion_pak; } features; } rom_info_t; -rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type); -rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type); +rom_cic_type_t rom_info_get_cic_type (rom_info_t *rom_info); +bool rom_info_get_cic_seed (rom_info_t *rom_info, uint8_t *seed); +rom_err_t rom_info_override_cic_type (path_t *path, rom_info_t *rom_info, rom_cic_type_t cic_type); + rom_save_type_t rom_info_get_save_type (rom_info_t *rom_info); +rom_err_t rom_info_override_save_type (path_t *path, rom_info_t *rom_info, rom_save_type_t save_type); + rom_tv_type_t rom_info_get_tv_type (rom_info_t *rom_info); +rom_err_t rom_info_override_tv_type (path_t *path, rom_info_t *rom_info, rom_tv_type_t tv_type); + rom_err_t rom_info_load (path_t *path, rom_info_t *rom_info); diff --git a/src/menu/sound.c b/src/menu/sound.c index d613b4f2..9e58d001 100644 --- a/src/menu/sound.c +++ b/src/menu/sound.c @@ -6,7 +6,7 @@ #define DEFAULT_FREQUENCY (44100) -#define NUM_BUFFERS (2) +#define NUM_BUFFERS (4) #define NUM_CHANNELS (2) diff --git a/src/menu/usb_comm.c b/src/menu/usb_comm.c index c823a3bd..fd218cd3 100644 --- a/src/menu/usb_comm.c +++ b/src/menu/usb_comm.c @@ -12,10 +12,12 @@ #define MAX_FILE_SIZE MiB(4) + /** @brief The supported USB commands structure. */ typedef struct { /** @brief The command identifier. */ const char *id; + /** @brief The command operation. */ void (*op) (menu_t *menu); } usb_comm_command_t; diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index 75ab0a4a..a7517946 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -135,6 +135,22 @@ static bool load_directory (menu_t *menu) { return false; } +static bool reload_directory (menu_t *menu) { + int selected = menu->browser.selected; + + if (load_directory(menu)) { + return true; + } + + menu->browser.selected = selected; + if (menu->browser.selected >= menu->browser.entries) { + menu->browser.selected = menu->browser.entries - 1; + } + menu->browser.entry = menu->browser.selected >= 0 ? &menu->browser.list[menu->browser.selected] : NULL; + + return false; +} + static bool push_directory (menu_t *menu, char *directory) { path_t *previous_directory = path_clone(menu->browser.directory); @@ -175,13 +191,11 @@ static bool pop_directory (menu_t *menu) { return false; } -static void show_properties (menu_t *menu) { +static void show_properties (menu_t *menu, void *arg) { menu->next_mode = MENU_MODE_FILE_INFO; } -static void delete_entry (menu_t *menu) { - int selected = menu->browser.selected; - +static void delete_entry (menu_t *menu, void *arg) { path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); if (menu->browser.entry->type == ENTRY_TYPE_DIR) { @@ -200,20 +214,13 @@ static void delete_entry (menu_t *menu) { path_free(path); - if (load_directory(menu)) { + if (reload_directory(menu)) { menu->browser.valid = false; menu_show_error(menu, "Couldn't refresh directory contents after delete operation"); - return; } - - menu->browser.selected = selected; - if (menu->browser.selected >= menu->browser.entries) { - menu->browser.selected = menu->browser.entries - 1; - } - menu->browser.entry = menu->browser.selected >= 0 ? &menu->browser.list[menu->browser.selected] : NULL; } -static void set_default_directory (menu_t *menu) { +static void set_default_directory (menu_t *menu, void *arg) { free(menu->settings.default_directory); menu->settings.default_directory = strdup(strip_sd_prefix(path_get(menu->browser.directory))); settings_save(&menu->settings); @@ -228,28 +235,17 @@ static component_context_menu_t entry_context_menu = { } }; -static void edit_settings (menu_t *menu) { - menu->next_mode = MENU_MODE_SETTINGS_EDITOR; -} - -static void show_system_info (menu_t *menu) { - menu->next_mode = MENU_MODE_SYSTEM_INFO; -} - -static void show_credits (menu_t *menu) { - menu->next_mode = MENU_MODE_CREDITS; -} - -static void edit_rtc (menu_t *menu) { - menu->next_mode = MENU_MODE_RTC; +static void set_menu_next_mode (menu_t *menu, void *arg) { + menu_mode_t next_mode = (menu_mode_t) (arg); + menu->next_mode = next_mode; } static component_context_menu_t settings_context_menu = { .list = { - { .text = "Edit settings", .action = edit_settings }, - { .text = "Show system info", .action = show_system_info }, - { .text = "Show credits", .action = show_credits }, - { .text = "Adjust RTC", .action = edit_rtc }, + { .text = "Edit settings", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_SETTINGS_EDITOR) }, + { .text = "Show system info", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_SYSTEM_INFO) }, + { .text = "Show credits", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_CREDITS) }, + { .text = "Adjust RTC", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_RTC) }, COMPONENT_CONTEXT_MENU_LIST_END, } }; @@ -386,18 +382,12 @@ void view_browser_init (menu_t *menu) { menu->browser.valid = true; } } + if (menu->browser.reload) { menu->browser.reload = false; - int selected = menu->browser.selected; - if (load_directory(menu)) { + if (reload_directory(menu)) { menu_show_error(menu, "Error while reloading current directory"); menu->browser.valid = false; - } else { - menu->browser.selected = selected; - if (menu->browser.selected >= menu->browser.entries) { - menu->browser.selected = menu->browser.entries - 1; - } - menu->browser.entry = menu->browser.selected >= 0 ? &menu->browser.list[menu->browser.selected] : NULL; } } } diff --git a/src/menu/views/credits.c b/src/menu/views/credits.c index a6e42a9a..dc1d0665 100644 --- a/src/menu/views/credits.c +++ b/src/menu/views/credits.c @@ -2,7 +2,11 @@ #ifndef MENU_VERSION -#define MENU_VERSION "0.0.0.6.ALPHA" +#define MENU_VERSION "Unknown" +#endif + +#ifndef BUILD_TIMESTAMP +#define BUILD_TIMESTAMP "Unknown" #endif @@ -28,7 +32,8 @@ static void draw (menu_t *menu, surface_t *d) { ALIGN_LEFT, VALIGN_TOP, "\n" "\n" - "Menu Revision: V%s\n" + "Menu version: %s\n" + "Build timestamp: %s\n" "\n" "Github:\n" " https://github.com/Polprzewodnikowy/N64FlashcartMenu\n" @@ -44,7 +49,8 @@ static void draw (menu_t *menu, surface_t *d) { " mini.c (BSD 2-Clause License)\n" " minimp3 (CC0 1.0 Universal)\n" " miniz (MIT License)", - MENU_VERSION + MENU_VERSION, + BUILD_TIMESTAMP ); component_actions_bar_text_draw( diff --git a/src/menu/views/load_disk.c b/src/menu/views/load_disk.c index 14d9d80b..0a8ebb62 100644 --- a/src/menu/views/load_disk.c +++ b/src/menu/views/load_disk.c @@ -126,9 +126,21 @@ static void load (menu_t *menu) { } menu->next_mode = MENU_MODE_BOOT; - menu->boot_params->device_type = load_rom ? BOOT_DEVICE_TYPE_ROM : BOOT_DEVICE_TYPE_64DD; - menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; - menu->boot_params->detect_cic_seed = true; + + if (load_rom) { + menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; + menu->boot_params->detect_cic_seed = rom_info_get_cic_seed(&menu->load.rom_info, &menu->boot_params->cic_seed); + switch (rom_info_get_tv_type(&menu->load.rom_info)) { + case ROM_TV_TYPE_PAL: menu->boot_params->tv_type = BOOT_TV_TYPE_PAL; break; + case ROM_TV_TYPE_NTSC: menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; break; + case ROM_TV_TYPE_MPAL: menu->boot_params->tv_type = BOOT_TV_TYPE_MPAL; break; + default: menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; break; + } + } else { + menu->boot_params->device_type = BOOT_DEVICE_TYPE_64DD; + menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; + menu->boot_params->detect_cic_seed = true; + } } diff --git a/src/menu/views/load_rom.c b/src/menu/views/load_rom.c index 6beeaa0f..c5da6ed4 100644 --- a/src/menu/views/load_rom.c +++ b/src/menu/views/load_rom.c @@ -8,15 +8,15 @@ static bool load_pending; static component_boxart_t *boxart; -static char *convert_error_message (disk_err_t err) { +static char *convert_error_message (rom_err_t err) { switch (err) { - case ROM_ERR_IO: return "I/O error during loading ROM information"; + case ROM_ERR_IO: return "I/O error during loading/storing ROM information"; case ROM_ERR_NO_FILE: return "Couldn't open ROM file"; default: return "Unknown ROM info load error"; } } -static const char *format_rom_endianness (endianness_t endianness) { +static const char *format_rom_endianness (rom_endianness_t endianness) { switch (endianness) { case ENDIANNESS_BIG: return "Big (default)"; case ENDIANNESS_LITTLE: return "Little (unsupported)"; @@ -25,7 +25,7 @@ static const char *format_rom_endianness (endianness_t endianness) { } } -static const char *format_rom_media_type (category_type_t media_type) { +static const char *format_rom_media_type (rom_category_type_t media_type) { switch (media_type) { case N64_CART: return "Cartridge"; case N64_DISK: return "Disk"; @@ -36,7 +36,7 @@ static const char *format_rom_media_type (category_type_t media_type) { } } -static const char *format_rom_destination_market (destination_type_t market_type) { +static const char *format_rom_destination_market (rom_destination_type_t market_type) { // TODO: These are all assumptions and should be corrected if required. // From http://n64devkit.square7.ch/info/submission/pal/01-01.html switch (market_type) { @@ -87,7 +87,7 @@ static const char *format_rom_tv_type (rom_tv_type_t tv_type) { } } -static char *format_rom_expansion_pak_info (expansion_pak_t expansion_pak_info) { +static const char *format_rom_expansion_pak_info (rom_expansion_pak_t expansion_pak_info) { switch (expansion_pak_info) { case EXPANSION_PAK_REQUIRED: return "Required"; case EXPANSION_PAK_RECOMMENDED: return "Recommended"; @@ -97,72 +97,94 @@ static char *format_rom_expansion_pak_info (expansion_pak_t expansion_pak_info) } } -static const char *format_cic_type (cic_type_t cic_type) { +static const char *format_cic_type (rom_cic_type_t cic_type) { switch (cic_type) { - case CIC_5101: return "5101"; - case CIC_5167: return "5167"; - case CIC_6101: return "6101"; - case CIC_7102: return "7102"; - case CIC_6102_7101: return "6102 / 7101"; - case CIC_x103: return "6103 / 7103"; - case CIC_x105: return "6105 / 7105"; - case CIC_x106: return "6106 / 7106"; - case CIC_8301: return "8301"; - case CIC_8302: return "8302"; - case CIC_8303: return "8303"; - case CIC_8401: return "8401"; - case CIC_8501: return "8501"; + case ROM_CIC_TYPE_5101: return "5101"; + case ROM_CIC_TYPE_5167: return "5167"; + case ROM_CIC_TYPE_6101: return "6101"; + case ROM_CIC_TYPE_7102: return "7102"; + case ROM_CIC_TYPE_x102: return "6102 / 7101"; + case ROM_CIC_TYPE_x103: return "6103 / 7103"; + case ROM_CIC_TYPE_x105: return "6105 / 7105"; + case ROM_CIC_TYPE_x106: return "6106 / 7106"; + case ROM_CIC_TYPE_8301: return "8301"; + case ROM_CIC_TYPE_8302: return "8302"; + case ROM_CIC_TYPE_8303: return "8303"; + case ROM_CIC_TYPE_8401: return "8401"; + case ROM_CIC_TYPE_8501: return "8501"; default: return "Unknown"; } } -static void set_save_type (menu_t *menu, rom_save_type_t save_type) { - rom_info_override_save_type(menu->load.rom_path, &menu->load.rom_info, save_type); +static void set_cic_type (menu_t *menu, void *arg) { + rom_cic_type_t cic_type = (rom_cic_type_t) (arg); + rom_err_t err = rom_info_override_cic_type(menu->load.rom_path, &menu->load.rom_info, cic_type); + if (err != ROM_OK) { + menu_show_error(menu, convert_error_message(err)); + } menu->browser.reload = true; } -static void set_save_type_automatic (menu_t *menu) { set_save_type(menu, SAVE_TYPE_AUTOMATIC); } -static void set_save_type_none (menu_t *menu) { set_save_type(menu, SAVE_TYPE_NONE); } -static void set_save_type_eeprom_4kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_EEPROM_4K); } -static void set_save_type_eeprom_16kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_EEPROM_16K); } -static void set_save_type_sram_256kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM); } -static void set_save_type_sram_768kbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM_BANKED); } -static void set_save_type_sram_1mbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_SRAM_128K); } -static void set_save_type_flash_ram_1mbit (menu_t *menu) { set_save_type(menu, SAVE_TYPE_FLASHRAM); } +static void set_save_type (menu_t *menu, void *arg) { + rom_save_type_t save_type = (rom_save_type_t) (arg); + rom_err_t err = rom_info_override_save_type(menu->load.rom_path, &menu->load.rom_info, save_type); + if (err != ROM_OK) { + menu_show_error(menu, convert_error_message(err)); + } + menu->browser.reload = true; +} -static component_context_menu_t set_save_type_context_menu = { .list = { - { .text = "Automatic", .action = set_save_type_automatic }, - { .text = "None", .action = set_save_type_none }, - { .text = "EEPROM 4kbit", .action = set_save_type_eeprom_4kbit }, - { .text = "EEPROM 16kbit", .action = set_save_type_eeprom_16kbit }, - { .text = "SRAM 256kbit", .action = set_save_type_sram_256kbit }, - { .text = "SRAM 768kbit", .action = set_save_type_sram_768kbit }, - { .text = "SRAM 1Mbit", .action = set_save_type_sram_1mbit }, - { .text = "FlashRAM 1Mbit", .action = set_save_type_flash_ram_1mbit }, +static void set_tv_type (menu_t *menu, void *arg) { + rom_tv_type_t tv_type = (rom_tv_type_t) (arg); + rom_err_t err = rom_info_override_tv_type(menu->load.rom_path, &menu->load.rom_info, tv_type); + if (err != ROM_OK) { + menu_show_error(menu, convert_error_message(err)); + } + menu->browser.reload = true; +} + +static component_context_menu_t set_cic_type_context_menu = { .list = { + {.text = "Automatic", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_AUTOMATIC) }, + {.text = "CIC-6101", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_6101) }, + {.text = "CIC-7102", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_7102) }, + {.text = "CIC-6102 / CIC-7101", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_x102) }, + {.text = "CIC-6103 / CIC-7103", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_x103) }, + {.text = "CIC-6105 / CIC-7105", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_x105) }, + {.text = "CIC-6106 / CIC-7106", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_x106) }, + {.text = "Aleck64 CIC-5101", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_5101) }, + {.text = "64DD ROM conversion CIC-5167", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_5167) }, + {.text = "NDDJ0 64DD IPL", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_8301) }, + {.text = "NDDJ1 64DD IPL", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_8302) }, + {.text = "NDDJ2 64DD IPL", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_8303) }, + {.text = "NDXJ0 64DD IPL", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_8401) }, + {.text = "NDDE0 64DD IPL", .action = set_cic_type, .arg = (void *) (ROM_CIC_TYPE_8501) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; -static void set_tv_type (menu_t *menu, rom_tv_type_t tv_type) { - rom_info_override_tv_type(menu->load.rom_path, &menu->load.rom_info, tv_type); - menu->browser.reload = true; -} - -static void set_tv_type_automatic (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_AUTOMATIC); } -static void set_tv_type_pal (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_PAL); } -static void set_tv_type_ntsc (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_NTSC); } -static void set_tv_type_mpal (menu_t *menu) { set_tv_type(menu, ROM_TV_TYPE_MPAL); } +static component_context_menu_t set_save_type_context_menu = { .list = { + { .text = "Automatic", .action = set_save_type, .arg = (void *) (SAVE_TYPE_AUTOMATIC) }, + { .text = "None", .action = set_save_type, .arg = (void *) (SAVE_TYPE_NONE) }, + { .text = "EEPROM 4kbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_EEPROM_4K) }, + { .text = "EEPROM 16kbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_EEPROM_16K) }, + { .text = "SRAM 256kbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_SRAM) }, + { .text = "SRAM 768kbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_SRAM_BANKED) }, + { .text = "SRAM 1Mbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_SRAM_128K) }, + { .text = "FlashRAM 1Mbit", .action = set_save_type, .arg = (void *) (SAVE_TYPE_FLASHRAM) }, + COMPONENT_CONTEXT_MENU_LIST_END, +}}; static component_context_menu_t set_tv_type_context_menu = { .list = { - { .text = "Automatic", .action = set_tv_type_automatic }, - { .text = "PAL", .action = set_tv_type_pal }, - { .text = "NTSC", .action = set_tv_type_ntsc }, - { .text = "MPAL", .action = set_tv_type_mpal }, + { .text = "Automatic", .action = set_tv_type, .arg = (void *) (ROM_TV_TYPE_AUTOMATIC) }, + { .text = "PAL", .action = set_tv_type, .arg = (void *) (ROM_TV_TYPE_PAL) }, + { .text = "NTSC", .action = set_tv_type, .arg = (void *) (ROM_TV_TYPE_NTSC) }, + { .text = "MPAL", .action = set_tv_type, .arg = (void *) (ROM_TV_TYPE_MPAL) }, COMPONENT_CONTEXT_MENU_LIST_END, }}; static component_context_menu_t options_context_menu = { .list = { - { .text = "Set save type", .submenu = &set_save_type_context_menu }, - { .text = "Set TV type", .submenu = &set_tv_type_context_menu }, + { .text = "Set CIC Type", .submenu = &set_cic_type_context_menu }, + { .text = "Set Save Type", .submenu = &set_save_type_context_menu }, + { .text = "Set TV Type", .submenu = &set_tv_type_context_menu }, COMPONENT_CONTEXT_MENU_LIST_END, }}; @@ -230,7 +252,7 @@ static void draw (menu_t *menu, surface_t *d) { format_rom_save_type(rom_info_get_save_type(&menu->load.rom_info)), format_rom_tv_type(rom_info_get_tv_type(&menu->load.rom_info)), format_rom_expansion_pak_info(menu->load.rom_info.features.expansion_pak), - format_cic_type(menu->load.rom_info.cic_type), + format_cic_type(rom_info_get_cic_type(&menu->load.rom_info)), menu->load.rom_info.boot_address, (menu->load.rom_info.libultra.version / 10.0f), menu->load.rom_info.libultra.revision, menu->load.rom_info.clock_rate @@ -281,8 +303,8 @@ static void load (menu_t *menu) { menu->next_mode = MENU_MODE_BOOT; menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; - menu->boot_params->detect_cic_seed = true; - switch(rom_info_get_tv_type(&menu->load.rom_info)) { + menu->boot_params->detect_cic_seed = rom_info_get_cic_seed(&menu->load.rom_info, &menu->boot_params->cic_seed); + switch (rom_info_get_tv_type(&menu->load.rom_info)) { case ROM_TV_TYPE_PAL: menu->boot_params->tv_type = BOOT_TV_TYPE_PAL; break; case ROM_TV_TYPE_NTSC: menu->boot_params->tv_type = BOOT_TV_TYPE_NTSC; break; case ROM_TV_TYPE_MPAL: menu->boot_params->tv_type = BOOT_TV_TYPE_MPAL; break; @@ -296,18 +318,20 @@ static void deinit (void) { void view_load_rom_init (menu_t *menu) { + load_pending = false; + if (menu->load.rom_path) { path_free(menu->load.rom_path); - menu->load.rom_path = NULL; } - load_pending = false; - menu->load.rom_path = path_clone_push(menu->browser.directory, menu->browser.entry->name); rom_err_t err = rom_info_load(menu->load.rom_path, &menu->load.rom_info); if (err != ROM_OK) { + path_free(menu->load.rom_path); + menu->load.rom_path = NULL; menu_show_error(menu, convert_error_message(err)); + return; } boxart = component_boxart_init(menu->load.rom_info.game_code); diff --git a/src/menu/views/settings_editor.c b/src/menu/views/settings_editor.c index c624ba1a..7158a0b3 100644 --- a/src/menu/views/settings_editor.c +++ b/src/menu/views/settings_editor.c @@ -1,13 +1,14 @@ #include "views.h" -static char *format_boolean_type (int state) { + +static const char *format_switch (bool state) { switch (state) { - case 0: return "Off"; - case 1: return "On"; - default: return "Unknown"; + case true: return "On"; + case false: return "Off"; } } + static void process (menu_t *menu) { if (menu->actions.back) { menu->next_mode = MENU_MODE_BROWSER; @@ -40,16 +41,15 @@ static void draw (menu_t *menu, surface_t *d) { "bgm_enabled: %s\n" "sound_enabled: %s\n" "rumble_enabled: %s\n", - format_boolean_type(menu->settings.pal60_enabled), - format_boolean_type(menu->settings.hidden_files_enabled), + format_switch(menu->settings.pal60_enabled), + format_switch(menu->settings.hidden_files_enabled), menu->settings.default_directory, - format_boolean_type(menu->settings.use_saves_folder), - format_boolean_type(menu->settings.bgm_enabled), - format_boolean_type(menu->settings.sound_enabled), - format_boolean_type(menu->settings.rumble_enabled) + format_switch(menu->settings.use_saves_folder), + format_switch(menu->settings.bgm_enabled), + format_switch(menu->settings.sound_enabled), + format_switch(menu->settings.rumble_enabled) ); - component_actions_bar_text_draw( ALIGN_LEFT, VALIGN_TOP, "\n" @@ -66,5 +66,6 @@ void view_settings_init (menu_t *menu) { void view_settings_display (menu_t *menu, surface_t *display) { process(menu); + draw(menu, display); } diff --git a/src/menu/views/system_info.c b/src/menu/views/system_info.c index a0ebfcad..02b78f72 100644 --- a/src/menu/views/system_info.c +++ b/src/menu/views/system_info.c @@ -7,27 +7,25 @@ static int joypad[4]; static int accessory[4]; -static char *format_accessory (int joypad) { +static const char *format_accessory (int joypad) { switch (accessory[joypad]) { - case JOYPAD_ACCESSORY_TYPE_RUMBLE_PAK: - return "[Rumble Pak is inserted]"; - case JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK: - return "[Controller Pak is inserted]"; - case JOYPAD_ACCESSORY_TYPE_TRANSFER_PAK: - return "[Transfer Pak is inserted]"; - case JOYPAD_ACCESSORY_TYPE_BIO_SENSOR: - return "[BIO Sensor is inserted]"; - case JOYPAD_ACCESSORY_TYPE_SNAP_STATION: - return "[Snap Station is inserted]"; - case JOYPAD_ACCESSORY_TYPE_NONE: - return ""; - default: - return "[unknown accessory inserted]"; + case JOYPAD_ACCESSORY_TYPE_RUMBLE_PAK: return "[Rumble Pak is inserted]"; + case JOYPAD_ACCESSORY_TYPE_CONTROLLER_PAK: return "[Controller Pak is inserted]"; + case JOYPAD_ACCESSORY_TYPE_TRANSFER_PAK: return "[Transfer Pak is inserted]"; + case JOYPAD_ACCESSORY_TYPE_BIO_SENSOR: return "[BIO Sensor is inserted]"; + case JOYPAD_ACCESSORY_TYPE_SNAP_STATION: return "[Snap Station is inserted]"; + case JOYPAD_ACCESSORY_TYPE_NONE: return ""; + default: return "[unknown accessory inserted]"; } } static void process (menu_t *menu) { + JOYPAD_PORT_FOREACH (port) { + joypad[port] = (joypad_get_style(port) != JOYPAD_STYLE_NONE); + accessory[port] = joypad_get_accessory_type(port); + } + if (menu->actions.back) { menu->next_mode = MENU_MODE_BROWSER; } @@ -53,10 +51,10 @@ static void draw (menu_t *menu, surface_t *d) { "\n" "Expansion PAK is %sinserted\n" "\n" - "JoyPad 1 is %sconnected %s\n" - "JoyPad 2 is %sconnected %s\n" - "JoyPad 3 is %sconnected %s\n" - "JoyPad 4 is %sconnected %s\n", + "Joypad 1 is %sconnected %s\n" + "Joypad 2 is %sconnected %s\n" + "Joypad 3 is %sconnected %s\n" + "Joypad 4 is %sconnected %s\n", menu->current_time >= 0 ? ctime(&menu->current_time) : "Unknown\n", is_memory_expanded() ? "" : "not ", (joypad[0]) ? "" : "not ", format_accessory(0), @@ -76,10 +74,7 @@ static void draw (menu_t *menu, surface_t *d) { void view_system_info_init (menu_t *menu) { - JOYPAD_PORT_FOREACH (port) { - joypad[port] = (joypad_get_style(port) != JOYPAD_STYLE_NONE); - accessory[port] = joypad_get_accessory_type(port); - } + // Nothing to initialize (yet) } void view_system_info_display (menu_t *menu, surface_t *display) { diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 2b7e0660..4d956b0d 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -23,12 +23,12 @@ void view_startup_display (menu_t *menu, surface_t *display); void view_browser_init (menu_t *menu); void view_browser_display (menu_t *menu, surface_t *display); -void view_system_info_init (menu_t *menu); -void view_system_info_display (menu_t *menu, surface_t *display); - void view_file_info_init (menu_t *menu); void view_file_info_display (menu_t *menu, surface_t *display); +void view_system_info_init (menu_t *menu); +void view_system_info_display (menu_t *menu, surface_t *display); + void view_image_viewer_init (menu_t *menu); void view_image_viewer_display (menu_t *menu, surface_t *display); @@ -38,18 +38,18 @@ void view_music_player_display (menu_t *menu, surface_t *display); void view_credits_init (menu_t *menu); void view_credits_display (menu_t *menu, surface_t *display); -void view_load_rom_init (menu_t *menu); -void view_load_rom_display (menu_t *menu, surface_t *display); - -void view_load_disk_init (menu_t *menu); -void view_load_disk_display (menu_t *menu, surface_t *display); - void view_settings_init (menu_t *menu); void view_settings_display (menu_t *menu, surface_t *display); void view_rtc_init (menu_t *menu); void view_rtc_display (menu_t *menu, surface_t *display); +void view_load_rom_init (menu_t *menu); +void view_load_rom_display (menu_t *menu, surface_t *display); + +void view_load_disk_init (menu_t *menu); +void view_load_disk_display (menu_t *menu, surface_t *display); + void view_load_emulator_init (menu_t *menu); void view_load_emulator_display (menu_t *menu, surface_t *display); From d85f24a0d8510942a5275405008e45ac8d5d7728 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Wed, 17 Jan 2024 14:47:31 +0000 Subject: [PATCH 2/5] Add RTC feature for flashcart (#58) ## Description Adds a feature to the flashcart to determine whether RTC is supported. This is at minimum required for correct handling of what to show on the main menu. It also will help with a future context menu to set the RTC time. ## Motivation and Context Some flashcarts (ED64 X5, V2.5, V2.0, V1.0 & ED64P ) do not support it. ## How Has This Been Tested? ## Screenshots ## Types of changes - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: - [ ] 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. Signed-off-by: GITHUB_USER --- src/flashcart/64drive/64drive.c | 1 + src/flashcart/flashcart.h | 1 + src/flashcart/sc64/sc64.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index b2ed3b36..bf0094c0 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -73,6 +73,7 @@ static flashcart_err_t d64_deinit (void) { static bool d64_has_feature (flashcart_features_t feature) { switch (feature) { case FLASHCART_FEATURE_64DD: return false; + case FLASHCART_FEATURE_RTC: return true; default: return false; } } diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index 0e97e807..0adb56e3 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -27,6 +27,7 @@ typedef enum { /** @brief List of optional supported flashcart features */ typedef enum { FLASHCART_FEATURE_64DD, + FLASHCART_FEATURE_RTC, } flashcart_features_t; /** @brief Flashcart save type enumeration */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index 58f4c450..895b6d5d 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -260,6 +260,7 @@ static flashcart_err_t sc64_deinit (void) { static bool sc64_has_feature (flashcart_features_t feature) { switch (feature) { case FLASHCART_FEATURE_64DD: return true; + case FLASHCART_FEATURE_RTC: return true; default: return false; } } From cc46a3b9fb5ecc8223e8065690d2e8796a0fbadd Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Wed, 17 Jan 2024 14:51:10 +0000 Subject: [PATCH 3/5] Add USB feature for flashcart (#85) ## Description Adds a feature to the flashcart to determine whether USB is supported. ## Motivation and Context Some flashcarts (ED64 X5, V2.5, V2.0, V1.0 & ED64P ) do not support it. ## How Has This Been Tested? ## Screenshots ## Types of changes - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: - [ ] 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. Signed-off-by: GITHUB_USER Co-authored-by: Mateusz Faderewski --- src/flashcart/64drive/64drive.c | 1 + src/flashcart/flashcart.h | 1 + src/flashcart/sc64/sc64.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/flashcart/64drive/64drive.c b/src/flashcart/64drive/64drive.c index bf0094c0..9b0b8b08 100644 --- a/src/flashcart/64drive/64drive.c +++ b/src/flashcart/64drive/64drive.c @@ -74,6 +74,7 @@ static bool d64_has_feature (flashcart_features_t feature) { switch (feature) { case FLASHCART_FEATURE_64DD: return false; case FLASHCART_FEATURE_RTC: return true; + case FLASHCART_FEATURE_USB: return true; default: return false; } } diff --git a/src/flashcart/flashcart.h b/src/flashcart/flashcart.h index 0adb56e3..001516bb 100644 --- a/src/flashcart/flashcart.h +++ b/src/flashcart/flashcart.h @@ -28,6 +28,7 @@ typedef enum { typedef enum { FLASHCART_FEATURE_64DD, FLASHCART_FEATURE_RTC, + FLASHCART_FEATURE_USB, } flashcart_features_t; /** @brief Flashcart save type enumeration */ diff --git a/src/flashcart/sc64/sc64.c b/src/flashcart/sc64/sc64.c index 895b6d5d..b7febf16 100644 --- a/src/flashcart/sc64/sc64.c +++ b/src/flashcart/sc64/sc64.c @@ -261,6 +261,7 @@ static bool sc64_has_feature (flashcart_features_t feature) { switch (feature) { case FLASHCART_FEATURE_64DD: return true; case FLASHCART_FEATURE_RTC: return true; + case FLASHCART_FEATURE_USB: return true; default: return false; } } From a2e50a9c82b41741beb304c3b72c0b6729c5b340 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Wed, 17 Jan 2024 14:54:30 +0000 Subject: [PATCH 4/5] Add flashcart submenu view (#86) ## Description Adds a view to show the flashcart information ## Motivation and Context Will be useful to show its features etc. ## How Has This Been Tested? ## Screenshots ## Types of changes - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: - [ ] 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. Signed-off-by: GITHUB_USER Co-authored-by: Mateusz Faderewski --- Makefile | 1 + src/menu/menu.c | 1 + src/menu/menu_state.h | 1 + src/menu/views/browser.c | 1 + src/menu/views/flashcart_info.c | 46 +++++++++++++++++++++++++++++++++ src/menu/views/views.h | 3 +++ 6 files changed, 53 insertions(+) create mode 100644 src/menu/views/flashcart_info.c diff --git a/Makefile b/Makefile index db6493d9..f9c10b67 100644 --- a/Makefile +++ b/Makefile @@ -64,6 +64,7 @@ SRCS = \ menu/views/system_info.c \ menu/views/settings_editor.c \ menu/views/rtc.c \ + menu/views/flashcart_info.c \ utils/fs.c FONTS = \ diff --git a/src/menu/menu.c b/src/menu/menu.c index 06e9ef2d..53bd497f 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -152,6 +152,7 @@ static view_t menu_views[] = { { MENU_MODE_CREDITS, view_credits_init, view_credits_display }, { MENU_MODE_SETTINGS_EDITOR, view_settings_init, view_settings_display }, { MENU_MODE_RTC, view_rtc_init, view_rtc_display }, + { MENU_MODE_FLASHCART, view_flashcart_info_init, view_flashcart_info_display }, { MENU_MODE_LOAD_ROM, view_load_rom_init, view_load_rom_display }, { MENU_MODE_LOAD_DISK, view_load_disk_init, view_load_disk_display }, { MENU_MODE_LOAD_EMULATOR, view_load_emulator_init, view_load_emulator_display }, diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 9fcee137..071ce99e 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -33,6 +33,7 @@ typedef enum { MENU_MODE_CREDITS, MENU_MODE_SETTINGS_EDITOR, MENU_MODE_RTC, + MENU_MODE_FLASHCART, MENU_MODE_LOAD_ROM, MENU_MODE_LOAD_DISK, MENU_MODE_LOAD_EMULATOR, diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index a7517946..f6c2c9de 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -246,6 +246,7 @@ static component_context_menu_t settings_context_menu = { { .text = "Show system info", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_SYSTEM_INFO) }, { .text = "Show credits", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_CREDITS) }, { .text = "Adjust RTC", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_RTC) }, + { .text = "Show cart info", .action = set_menu_next_mode, .arg = (void *) (MENU_MODE_FLASHCART) }, COMPONENT_CONTEXT_MENU_LIST_END, } }; diff --git a/src/menu/views/flashcart_info.c b/src/menu/views/flashcart_info.c new file mode 100644 index 00000000..084cc073 --- /dev/null +++ b/src/menu/views/flashcart_info.c @@ -0,0 +1,46 @@ +#include "views.h" + + +static void process (menu_t *menu) { + if (menu->actions.back) { + menu->next_mode = MENU_MODE_BROWSER; + } +} + +static void draw (menu_t *menu, surface_t *d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + component_layout_draw(); + + component_main_text_draw( + ALIGN_CENTER, VALIGN_TOP, + "FLASHCART INFORMATION\n" + ); + + component_main_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "\n" + ); + + + component_actions_bar_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "B: Back" + ); + + rdpq_detach_show(); +} + + +void view_flashcart_info_init (menu_t *menu) { + // Nothing to initialize (yet) +} + +void view_flashcart_info_display (menu_t *menu, surface_t *display) { + process(menu); + draw(menu, display); +} diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 4d956b0d..74342dcc 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -44,6 +44,9 @@ void view_settings_display (menu_t *menu, surface_t *display); void view_rtc_init (menu_t *menu); void view_rtc_display (menu_t *menu, surface_t *display); +void view_flashcart_info_init (menu_t *menu); +void view_flashcart_info_display (menu_t *menu, surface_t *display); + void view_load_rom_init (menu_t *menu); void view_load_rom_display (menu_t *menu, surface_t *display); From 14e45c023020d2ff0bf93db2b818d33d935f41f7 Mon Sep 17 00:00:00 2001 From: Robin Jones Date: Wed, 17 Jan 2024 16:03:00 +0000 Subject: [PATCH 5/5] Add Text viewer (#87) ## Description Adds a basic text viewer. It does not (yet) support full file content. superseeds #21 ## Motivation and Context There were too many changes to merge from the original PR. ## How Has This Been Tested? On an SC64 via devcontainer. ## Screenshots ## Types of changes - [x] Improvement (non-breaking change that adds a new feature) - [ ] Bug fix (fixes an issue) - [ ] Breaking change (breaking change) - [ ] Config and build (change in the configuration and build system, has no impact on code or features) ## Checklist: - [ ] 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. Signed-off-by: GITHUB_USER --------- Co-authored-by: Mateusz Faderewski Co-authored-by: Mateusz Faderewski --- Makefile | 1 + src/menu/menu.c | 1 + src/menu/menu_state.h | 2 + src/menu/views/browser.c | 11 +++++ src/menu/views/text_viewer.c | 78 ++++++++++++++++++++++++++++++++++++ src/menu/views/views.h | 3 ++ 6 files changed, 96 insertions(+) create mode 100644 src/menu/views/text_viewer.c diff --git a/Makefile b/Makefile index f9c10b67..7c0ec049 100644 --- a/Makefile +++ b/Makefile @@ -56,6 +56,7 @@ SRCS = \ menu/views/fault.c \ menu/views/file_info.c \ menu/views/image_viewer.c \ + menu/views/text_viewer.c \ menu/views/load_disk.c \ menu/views/load_emulator.c \ menu/views/load_rom.c \ diff --git a/src/menu/menu.c b/src/menu/menu.c index 53bd497f..1b8832cb 100644 --- a/src/menu/menu.c +++ b/src/menu/menu.c @@ -148,6 +148,7 @@ static view_t menu_views[] = { { MENU_MODE_FILE_INFO, view_file_info_init, view_file_info_display }, { MENU_MODE_SYSTEM_INFO, view_system_info_init, view_system_info_display }, { MENU_MODE_IMAGE_VIEWER, view_image_viewer_init, view_image_viewer_display }, + { MENU_MODE_TEXT_VIEWER, view_text_viewer_init, view_text_viewer_display }, { MENU_MODE_MUSIC_PLAYER, view_music_player_init, view_music_player_display }, { MENU_MODE_CREDITS, view_credits_init, view_credits_display }, { MENU_MODE_SETTINGS_EDITOR, view_settings_init, view_settings_display }, diff --git a/src/menu/menu_state.h b/src/menu/menu_state.h index 071ce99e..f0d93492 100644 --- a/src/menu/menu_state.h +++ b/src/menu/menu_state.h @@ -29,6 +29,7 @@ typedef enum { MENU_MODE_FILE_INFO, MENU_MODE_SYSTEM_INFO, MENU_MODE_IMAGE_VIEWER, + MENU_MODE_TEXT_VIEWER, MENU_MODE_MUSIC_PLAYER, MENU_MODE_CREDITS, MENU_MODE_SETTINGS_EDITOR, @@ -50,6 +51,7 @@ typedef enum { ENTRY_TYPE_EMULATOR, ENTRY_TYPE_SAVE, ENTRY_TYPE_IMAGE, + ENTRY_TYPE_TEXT, ENTRY_TYPE_MUSIC, ENTRY_TYPE_OTHER, } entry_type_t; diff --git a/src/menu/views/browser.c b/src/menu/views/browser.c index f6c2c9de..01cdb41b 100644 --- a/src/menu/views/browser.c +++ b/src/menu/views/browser.c @@ -14,6 +14,7 @@ static const char *disk_extensions[] = { "ndd", NULL }; static const char *emulator_extensions[] = { "nes", "sfc", "smc", "gb", "gbc", "sms", "gg", "sg", NULL }; static const char *save_extensions[] = { "sav", NULL }; // TODO: "eep", "sra", "srm", "fla" could be used if transfered from different flashcarts. static const char *image_extensions[] = { "png", NULL }; +static const char *text_extensions[] = { "txt", "ini", "yml", "yaml", NULL }; static const char *music_extensions[] = { "mp3", NULL }; @@ -46,6 +47,10 @@ static int compare_entry (const void *pa, const void *pb) { return -1; } else if (b->type == ENTRY_TYPE_IMAGE) { return 1; + } else if (a->type == ENTRY_TYPE_TEXT) { + return -1; + } else if (b->type == ENTRY_TYPE_TEXT) { + return 1; } else if (a->type == ENTRY_TYPE_MUSIC) { return -1; } else if (b->type == ENTRY_TYPE_MUSIC) { @@ -110,6 +115,8 @@ static bool load_directory (menu_t *menu) { entry->type = ENTRY_TYPE_SAVE; } else if (file_has_extensions(info.fname, image_extensions)) { entry->type = ENTRY_TYPE_IMAGE; + } else if (file_has_extensions(info.fname, text_extensions)) { + entry->type = ENTRY_TYPE_TEXT; } else if (file_has_extensions(info.fname, music_extensions)) { entry->type = ENTRY_TYPE_MUSIC; } else { @@ -297,6 +304,9 @@ static void process (menu_t *menu) { case ENTRY_TYPE_IMAGE: menu->next_mode = MENU_MODE_IMAGE_VIEWER; break; + case ENTRY_TYPE_TEXT: + menu->next_mode = MENU_MODE_TEXT_VIEWER; + break; case ENTRY_TYPE_MUSIC: menu->next_mode = MENU_MODE_MUSIC_PLAYER; break; @@ -334,6 +344,7 @@ static void draw (menu_t *menu, surface_t *d) { case ENTRY_TYPE_ROM: action = "A: Load"; break; case ENTRY_TYPE_DISK: action = "A: Load"; break; case ENTRY_TYPE_IMAGE: action = "A: Show"; break; + case ENTRY_TYPE_TEXT: action = "A: View"; break; case ENTRY_TYPE_MUSIC: action = "A: Play"; break; default: action = "A: Info"; break; } diff --git a/src/menu/views/text_viewer.c b/src/menu/views/text_viewer.c new file mode 100644 index 00000000..adef2df9 --- /dev/null +++ b/src/menu/views/text_viewer.c @@ -0,0 +1,78 @@ +#include + +#include "utils/fs.h" +#include "views.h" + +static char *file_content; + +static void process (menu_t *menu) { + if (menu->actions.back) { + menu->next_mode = MENU_MODE_BROWSER; + } +} + +static void draw (menu_t *menu, surface_t *d) { + rdpq_attach(d, NULL); + + component_background_draw(); + + component_layout_draw(); + + component_main_text_draw( + ALIGN_CENTER, VALIGN_TOP, + "TEXT VIEWER\n" + "\n" + ); + + component_main_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "\n" + "%s\n", + file_content + ); + + + component_actions_bar_text_draw( + ALIGN_LEFT, VALIGN_TOP, + "\n" + "B: Back" + ); + + rdpq_detach_show(); +} + + +void view_text_viewer_init (menu_t *menu) { + path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); + + uint32_t file_size = file_get_size(path_get(path)); + + if (file_size > 1024) { // FIXME: this is just a placeholder until scrolling is implemented. + file_size = 1024; // For the moment, we just set it to that, since any more would be a waste. + } + + file_content = calloc(file_size, 1); + + // read file content + FIL fil; + UINT br; + + if (f_open(&fil, strip_sd_prefix(path_get(path)), FA_READ) != FR_OK) { + debugf("Error loading file\n"); + } + if (f_read(&fil, file_content, file_size, &br) != FR_OK) { + f_close(&fil); + debugf("Error loading file content\n"); + } + if (f_close(&fil) != FR_OK) { + debugf("Error closing file\n"); + } + + path_free(path); +} + +void view_text_viewer_display (menu_t *menu, surface_t *display) { + process(menu); + draw(menu, display); +} diff --git a/src/menu/views/views.h b/src/menu/views/views.h index 74342dcc..8da900dc 100644 --- a/src/menu/views/views.h +++ b/src/menu/views/views.h @@ -32,6 +32,9 @@ void view_system_info_display (menu_t *menu, surface_t *display); void view_image_viewer_init (menu_t *menu); void view_image_viewer_display (menu_t *menu, surface_t *display); +void view_text_viewer_init (menu_t *menu); +void view_text_viewer_display (menu_t *menu, surface_t *display); + void view_music_player_init (menu_t *menu); void view_music_player_display (menu_t *menu, surface_t *display);