Browser directory path now always include sd:/ prefix

This commit is contained in:
Mateusz Faderewski 2023-08-09 20:41:54 +02:00
parent cf78d9a0a2
commit 12dead7a6a
11 changed files with 189 additions and 191 deletions

View File

@ -15,7 +15,7 @@
#include "views/views.h"
#define TV_TYPE_RAM *((uint32_t *) (0x80000300))
#define TV_TYPE_RAM *((uint32_t *) (0x80000300))
#define CACHE_DIRECTORY "sd:/menu/cache"
#define BACKGROUND_CACHE "sd:/menu/cache/background.data"
@ -62,9 +62,10 @@ static void menu_init (boot_params_t *boot_params) {
menu->boot_params = boot_params;
bool default_directory_exists = directory_exists(menu->settings.default_directory);
char *init_directory = default_directory_exists ? menu->settings.default_directory : "";
menu->browser.valid = false;
menu->browser.directory = path_init(default_directory_exists ? menu->settings.default_directory : NULL);
menu->browser.directory = path_init("sd:/", init_directory);
tv_type = get_tv_type();
if ((tv_type == TV_PAL) && menu->settings.pal60) {

View File

@ -84,6 +84,7 @@ typedef struct {
path_t *directory;
entry_t list[BROWSER_LIST_SIZE];
int entries;
entry_t *entry;
int selected;
} browser;
} menu_t;

View File

@ -19,7 +19,7 @@ static void path_resize (path_t *path, size_t min_length) {
assert(path->buffer != NULL);
}
path_t *path_init (char *string) {
static path_t *path_create (char *string) {
if (string == NULL) {
string = "";
}
@ -28,6 +28,31 @@ path_t *path_init (char *string) {
path_resize(path, strlen(string));
memset(path->buffer, 0, path->capacity + 1);
strcpy(path->buffer, string);
path->root = path->buffer;
return path;
}
static void path_append (path_t *path, char *string) {
size_t buffer_length = strlen(path->buffer);
size_t string_length = strlen(string);
size_t new_path_length = buffer_length + string_length;
if (new_path_length > path->capacity) {
path_resize(path, new_path_length);
}
strcat(path->buffer, string);
}
path_t *path_init (char *prefix, char *string) {
path_t *path = path_create(prefix);
size_t prefix_length = strlen(prefix);
if ((prefix_length > 0) && (prefix[prefix_length - 1] == '/')) {
path->root = path->buffer + prefix_length - 1;
} else {
path->root = path->buffer + prefix_length;
path_append(path, "/");
}
path_push(path, string);
return path;
}
@ -39,7 +64,15 @@ void path_free (path_t *path) {
}
path_t *path_clone (path_t *path) {
return path_init(path->buffer);
path_t *cloned = path_create(path->buffer);
cloned->root = cloned->buffer + (path->root - path->buffer);
return cloned;
}
path_t *path_clone_push (path_t *path, char *string) {
path_t *cloned = path_clone(path);
path_push(cloned, string);
return cloned;
}
char *path_get (path_t *path) {
@ -47,26 +80,12 @@ char *path_get (path_t *path) {
}
char *path_last_get (path_t *path) {
char *last_slash = strrchr(path->buffer, '/');
return (last_slash == NULL) ? path->buffer : (last_slash + 1);
char *last_slash = strrchr(path->root, '/');
return (last_slash == NULL) ? path->root : (last_slash + 1);
}
bool path_is_root (path_t *path) {
return (strcmp(path->buffer, "") == 0) || (strcmp(path->buffer, "/") == 0);
}
void path_append (path_t *path, char *string) {
size_t buffer_length = strlen(path->buffer);
size_t string_length = strlen(string);
size_t new_path_length = buffer_length + string_length;
if (new_path_length > path->capacity) {
path_resize(path, new_path_length);
}
strcat(path->buffer, string);
}
void path_concat (path_t *dst, path_t *src) {
path_append(dst, src->buffer);
return (strcmp(path->root, "/") == 0);
}
void path_push (path_t *path, char *string) {
@ -80,8 +99,13 @@ void path_push (path_t *path, char *string) {
}
void path_pop (path_t *path) {
char *last_slash = strrchr(path->buffer, '/');
if (last_slash != NULL) {
if (path_is_root(path)) {
return;
}
char *last_slash = strrchr(path->root, '/');
if (last_slash == path->root) {
*(last_slash + 1) = '\0';
} else if (last_slash != NULL) {
*last_slash = '\0';
}
}

View File

@ -14,18 +14,18 @@
/** @brief Path Structure */
typedef struct {
char *buffer;
char *root;
size_t capacity;
} path_t;
path_t *path_init (char *string);
path_t *path_init (char *prefix, char *string);
void path_free (path_t *path);
path_t *path_clone (path_t *string);
path_t *path_clone_push (path_t *path, char *string);
char *path_get (path_t *path);
char *path_last_get (path_t *path);
bool path_is_root (path_t *path);
void path_append (path_t *path, char *string);
void path_concat (path_t *dst, path_t *str);
void path_push (path_t *path, char *string);
void path_pop (path_t *path);
char *path_ext_get (path_t *path);

View File

@ -38,12 +38,9 @@ uint8_t extract_homebrew_save_type(uint8_t save_type) {
* @brief Reads the N64 ROM header from a file. @see https://n64brew.dev/wiki/ROM_Header
*/
rom_header_t file_read_rom_header(char *path) {
char *sd_path = calloc(4 + strlen(path) + 1, sizeof(char));
sprintf(sd_path, "sd:/%s", path);
FILE *fp = fopen(path, "rb");
FILE *fp = fopen(sd_path, "rb");
debugf("loading path: %s\n", sd_path);
debugf("loading path: %s\n", path);
if (!fp) {
debugf("Error loading rom file header\n");
}
@ -82,8 +79,7 @@ rom_header_t file_read_rom_header(char *path) {
fclose(fp);
free(sd_path);
// FIXME: memory leak, rom header is copied, pointer should be returned instead or data freed before returning
return *rom_header;
}

View File

@ -58,10 +58,12 @@ static bool load_directory (menu_t *menu) {
for (int i = menu->browser.entries - 1; i >= 0; i--) {
free(menu->browser.list[i].name);
}
menu->browser.entries = 0;
menu->browser.selected = -1;
menu->browser.entry = NULL;
if (f_opendir(&dir, path_get(menu->browser.directory)) != FR_OK) {
if (f_opendir(&dir, strip_sd_prefix(path_get(menu->browser.directory))) != FR_OK) {
return true;
}
@ -118,6 +120,7 @@ static bool load_directory (menu_t *menu) {
if (menu->browser.entries > 0) {
menu->browser.selected = 0;
menu->browser.entry = &menu->browser.list[menu->browser.selected];
}
qsort(menu->browser.list, menu->browser.entries, sizeof(entry_t), compare_entry);
@ -155,6 +158,7 @@ static bool pop_directory (menu_t *menu) {
for (int i = 0; i < menu->browser.entries; i++) {
if (strcmp(menu->browser.list[i].name, path_last_get(previous_directory)) == 0) {
menu->browser.selected = i;
menu->browser.entry = &menu->browser.list[menu->browser.selected];
break;
}
}
@ -180,14 +184,13 @@ static void process (menu_t *menu) {
menu->browser.selected = menu->browser.entries - 1;
}
}
menu->browser.entry = &menu->browser.list[menu->browser.selected];
}
if (menu->actions.enter && menu->browser.selected >= 0) {
entry_t *entry = &menu->browser.list[menu->browser.selected];
switch (entry->type) {
if (menu->actions.enter && menu->browser.entry) {
switch (menu->browser.entry->type) {
case ENTRY_TYPE_DIR:
if (push_directory(menu, entry->name)) {
if (push_directory(menu, menu->browser.entry->name)) {
menu->browser.valid = false;
menu_show_error(menu, "Couldn't open next directory");
}
@ -213,7 +216,7 @@ static void process (menu_t *menu) {
menu->browser.valid = false;
menu_show_error(menu, "Couldn't open last directory");
}
} else if (menu->actions.file_info && menu->browser.selected >= 0) {
} else if (menu->actions.file_info && menu->browser.entry) {
menu->next_mode = MENU_MODE_FILE_INFO;
} else if (menu->actions.system_info) {
menu->next_mode = MENU_MODE_SYSTEM_INFO;
@ -234,12 +237,14 @@ static void draw (menu_t *menu, surface_t *d) {
const char *action = NULL;
switch (menu->browser.list[menu->browser.selected].type) {
case ENTRY_TYPE_DIR: action = "A: Enter"; break;
case ENTRY_TYPE_ROM: action = "A: Load"; break;
case ENTRY_TYPE_IMAGE: action = "A: Show"; break;
case ENTRY_TYPE_MUSIC: action = "A: Play"; break;
default: action = "A: Info"; break;
if (menu->browser.entry) {
switch (menu->browser.entry->type) {
case ENTRY_TYPE_DIR: action = "A: Enter"; break;
case ENTRY_TYPE_ROM: action = "A: Load"; break;
case ENTRY_TYPE_IMAGE: action = "A: Show"; break;
case ENTRY_TYPE_MUSIC: action = "A: Play"; break;
default: action = "A: Info"; break;
}
}
component_actions_bar_text_draw(
@ -276,7 +281,7 @@ void view_browser_init (menu_t *menu) {
if (!menu->browser.valid) {
if (load_directory(menu)) {
path_free(menu->browser.directory);
menu->browser.directory = path_init(NULL);
menu->browser.directory = path_init("sd:/", "");
menu_show_error(menu, "Error while opening initial directory");
} else {
menu->browser.valid = true;

View File

@ -65,7 +65,7 @@ static void draw (menu_t *menu, surface_t *d) {
"ENTRY INFORMATION\n"
"\n"
"%s",
menu->browser.list[menu->browser.selected].name
menu->browser.entry->name
);
component_main_text_draw(
@ -99,14 +99,13 @@ static void draw (menu_t *menu, surface_t *d) {
void view_file_info_init (menu_t *menu) {
path_t *file = path_clone(menu->browser.directory);
path_push(file, menu->browser.list[menu->browser.selected].name);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
if (f_stat(strip_sd_prefix(path_get(file)), &info) != FR_OK) {
if (f_stat(strip_sd_prefix(path_get(path)), &info) != FR_OK) {
menu_show_error(menu, "Couldn't obtain file information");
}
path_free(file);
path_free(path);
}
void view_file_info_display (menu_t *menu, surface_t *display) {

View File

@ -73,7 +73,7 @@ static void draw (menu_t *menu, surface_t *d) {
component_messagebox_draw(
"Set \"%s\" as background image?\n\n"
"A: Yes, B: Back",
menu->browser.list[menu->browser.selected].name
menu->browser.entry->name
);
} else if (image_set_as_background) {
component_messagebox_draw("Preparing background…");
@ -105,8 +105,7 @@ void view_image_viewer_init (menu_t *menu) {
image_set_as_background = false;
image = NULL;
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
png_err_t err = png_decoder_start(path_get(path), 640, 480, image_callback, menu);
if (err != PNG_OK) {

View File

@ -158,7 +158,7 @@ static void draw (menu_t *menu, surface_t *d) {
"N64 ROM information\n"
"\n"
"%s",
menu->browser.list[menu->browser.selected].name
menu->browser.entry->name
);
component_main_text_draw(
@ -243,8 +243,7 @@ static flashcart_save_type_t convert_save_type (db_savetype_t save_type) {
static void load (menu_t *menu) {
menu->next_mode = MENU_MODE_BOOT;
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
bool byte_swap = (rom_header.config_flags == ROM_MID_BIG_ENDIAN);
menu->flashcart_error = flashcart_load_rom(path_get(path), byte_swap, draw_progress);
@ -279,8 +278,7 @@ static void deinit (void) {
void view_load_init (menu_t *menu) {
load_pending = false;
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
rom_header = file_read_rom_header(path_get(path));

View File

@ -2,8 +2,8 @@
#include "boot/boot.h"
#include "flashcart/flashcart.h"
#include "views.h"
#include "utils/fs.h"
#include "views.h"
#ifndef EMULATOR_FOLDER
#define EMULATOR_FOLDER "/emulators/"
@ -14,127 +14,10 @@ static const char *emu_gameboy_rom_extensions[] = { "gb", NULL };
static const char *emu_gameboy_color_rom_extensions[] = { "gbc", NULL };
static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL };
const uint32_t eum_rom_start_address = 0x200000;
static const uint32_t eum_rom_start_address = 0x200000;
static bool load_pending;
static void draw_progress (float progress) {
surface_t *d = display_try_get();
if (d) {
rdpq_attach(d, NULL);
component_background_draw();
component_loader_draw(progress);
rdpq_detach_show();
}
}
static void load_emulator_nes_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.nes")) { // || neon64bu.rom
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.nes", false, draw_progress);
/* Combine EMU and ROM before loading. See https://github.com/hcs64/neon64v2/tree/master/pkg */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_SRAM_BANKED);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load_emulator_gameboy_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.gb")) { // || gb.v64
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gb", false, draw_progress);
/* Combine EMU and ROM before loading. */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load_emulator_gameboy_color_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.gbc")) { // || gbc.v64
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gbc", false, draw_progress);
/* Combine EMU and ROM before loading. */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load (menu_t *menu) {
menu->next_mode = MENU_MODE_BOOT;
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
if (file_has_extensions (path_get(path), emu_nes_rom_extensions)) {
load_emulator_nes_rom(path, menu);
}
else if (file_has_extensions (path_get(path), emu_gameboy_rom_extensions)) {
load_emulator_gameboy_rom(path, menu);
}
else if (file_has_extensions (path_get(path), emu_gameboy_color_rom_extensions)) {
load_emulator_gameboy_color_rom(path, menu);
}
else if (file_has_extensions (path_get(path), emu_sega_rom_extensions)) {
//load_emulator_sega_rom(path, menu);
}
path_free(path);
menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM;
menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH;
menu->boot_params->detect_cic_seed = true;
}
static void process (menu_t *menu) {
if (menu->actions.enter) {
@ -161,35 +44,128 @@ static void draw (menu_t *menu, surface_t *d) {
"Rom Name\n"
"\n"
"%s",
menu->browser.list[menu->browser.selected].name
menu->browser.entry->name
);
component_actions_bar_text_draw(
ALIGN_LEFT, VALIGN_TOP,
"A: Load and run Emulator ROM\n"
"B: Exit"
);
}
rdpq_detach_show();
}
static void draw_progress (float progress) {
surface_t *d = display_try_get();
if (d) {
rdpq_attach(d, NULL);
component_background_draw();
component_loader_draw(progress);
rdpq_detach_show();
}
}
static void load_emulator_nes_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.nes")) { // || neon64bu.rom
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.nes", false, draw_progress);
/* Combine EMU and ROM before loading. See https://github.com/hcs64/neon64v2/tree/master/pkg */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_SRAM_BANKED);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load_emulator_gameboy_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.gb")) { // || gb.v64
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gb", false, draw_progress);
/* Combine EMU and ROM before loading. */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load_emulator_gameboy_color_rom (path_t *path, menu_t *menu) {
if (file_exists(EMULATOR_FOLDER"emu.gbc")) { // || gbc.v64
menu->flashcart_error = flashcart_load_rom(EMULATOR_FOLDER"emu.gbc", false, draw_progress);
/* Combine EMU and ROM before loading. */
menu->flashcart_error = flashcart_load_file(path_get(path), eum_rom_start_address);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), FLASHCART_SAVE_TYPE_FLASHRAM);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
}
}
static void load (menu_t *menu) {
menu->next_mode = MENU_MODE_BOOT;
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
if (file_has_extensions(path_get(path), emu_nes_rom_extensions)) {
load_emulator_nes_rom(path, menu);
} else if (file_has_extensions(path_get(path), emu_gameboy_rom_extensions)) {
load_emulator_gameboy_rom(path, menu);
} else if (file_has_extensions(path_get(path), emu_gameboy_color_rom_extensions)) {
load_emulator_gameboy_color_rom(path, menu);
} else if (file_has_extensions(path_get(path), emu_sega_rom_extensions)) {
//load_emulator_sega_rom(path, menu);
}
path_free(path);
menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM;
menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH;
menu->boot_params->detect_cic_seed = true;
}
void view_load_emulator_init (menu_t *menu) {
load_pending = false;
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
path_free(path);
}
void view_load_emulator_display (menu_t *menu, surface_t *display) {
process(menu);
draw(menu, display);
if (load_pending) {
load_pending = false;
load(menu);

View File

@ -81,7 +81,7 @@ static void draw (menu_t *menu, surface_t *d) {
"MUSIC PLAYER\n"
"\n"
"%s",
menu->browser.list[menu->browser.selected].name
menu->browser.entry->name
);
char formatted_track_elapsed_length[64];
@ -138,8 +138,7 @@ void view_music_player_init (menu_t *menu) {
return;
}
path_t *path = path_clone(menu->browser.directory);
path_push(path, menu->browser.list[menu->browser.selected].name);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
err = mp3player_load(path_get(path));
if (err != MP3PLAYER_OK) {