Added option to put saves in subdirectory + moved ROM loading procedure outside of views

This commit is contained in:
Mateusz Faderewski 2023-08-18 22:19:01 +02:00
parent 20275f5b21
commit a1d20ae36e
12 changed files with 232 additions and 140 deletions

View File

@ -28,6 +28,7 @@ SRCS = \
libs/miniz/miniz_zip.c \ libs/miniz/miniz_zip.c \
libs/miniz/miniz.c \ libs/miniz/miniz.c \
menu/actions.c \ menu/actions.c \
menu/cart_load.c \
menu/components/background.c \ menu/components/background.c \
menu/components/boxart.c \ menu/components/boxart.c \
menu/components/common.c \ menu/components/common.c \
@ -47,7 +48,7 @@ SRCS = \
menu/views/file_info.c \ menu/views/file_info.c \
menu/views/image_viewer.c \ menu/views/image_viewer.c \
menu/views/load_emulator.c \ menu/views/load_emulator.c \
menu/views/load.c \ menu/views/load_rom.c \
menu/views/music_player.c \ menu/views/music_player.c \
menu/views/startup.c \ menu/views/startup.c \
menu/views/system_info.c \ menu/views/system_info.c \

142
src/menu/cart_load.c Normal file
View File

@ -0,0 +1,142 @@
#include "cart_load.h"
#include "path.h"
#include "utils/fs.h"
#define SAVES_SUBDIRECTORY "saves"
#define EMU_LOCATION "/emulators"
static bool create_saves_subdirectory (menu_t *menu) {
path_t *save_folder_path = path_clone_push(menu->browser.directory, SAVES_SUBDIRECTORY);
bool error = directory_create(path_get(save_folder_path));
path_free(save_folder_path);
return error;
}
static flashcart_save_type_t convert_save_type (rom_header_t *header) {
switch (rom_db_match_save_type(*header)) {
case DB_SAVE_TYPE_EEPROM_4K:
return FLASHCART_SAVE_TYPE_EEPROM_4K;
case DB_SAVE_TYPE_EEPROM_16K:
return FLASHCART_SAVE_TYPE_EEPROM_16K;
case DB_SAVE_TYPE_SRAM:
return FLASHCART_SAVE_TYPE_SRAM;
case DB_SAVE_TYPE_SRAM_BANKED:
return FLASHCART_SAVE_TYPE_SRAM_BANKED;
case DB_SAVE_TYPE_SRAM_128K:
return FLASHCART_SAVE_TYPE_SRAM_128K;
case DB_SAVE_TYPE_FLASHRAM:
return FLASHCART_SAVE_TYPE_FLASHRAM;
default:
return FLASHCART_SAVE_TYPE_NONE;
}
}
char *cart_load_convert_error_message (cart_load_err_t err) {
switch (err) {
case CART_LOAD_ERR_SAVES_SUBDIR: return "Could not create saves subdirectory";
case CART_LOAD_ERR_ROM: return "Error during ROM loading";
case CART_LOAD_ERR_SAVE: return "Error during save creation or loading";
case CART_LOAD_ERR_EMU_NOT_FOUND: return "Emulator ROM not found";
case CART_LOAD_ERR_EMU: return "Error during emulator ROM loading";
case CART_LOAD_ERR_EMU_ROM: return "Error during emulated ROM loading";
default: return "Unknown cart load error";
}
}
cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header, flashcart_progress_callback_t progress) {
if (menu->settings.use_saves_folder) {
if (create_saves_subdirectory(menu)) {
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
bool byte_swap = (header->config_flags == ROM_MID_BIG_ENDIAN);
menu->flashcart_error = flashcart_load_rom(path_get(path), byte_swap, progress);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_ROM;
}
path_ext_replace(path, "sav");
if (menu->settings.use_saves_folder) {
path_push_subdir(path, SAVES_SUBDIRECTORY);
}
menu->flashcart_error = flashcart_load_save(path_get(path), convert_save_type(header));
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_SAVE;
}
path_free(path);
return CART_LOAD_OK;
}
cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress) {
if (menu->settings.use_saves_folder) {
if (create_saves_subdirectory(menu)) {
return CART_LOAD_ERR_SAVES_SUBDIR;
}
}
path_t *path = path_init("sd:/", EMU_LOCATION);
flashcart_save_type_t save_type = FLASHCART_SAVE_TYPE_NONE;
uint32_t emulated_rom_offset = 0x200000;
switch (emu_type) {
case CART_LOAD_EMU_TYPE_NES:
path_push(path, "emu.nes");
save_type = FLASHCART_SAVE_TYPE_SRAM_BANKED;
break;
case CART_LOAD_EMU_TYPE_GAMEBOY:
path_push(path, "emu.gb");
save_type = FLASHCART_SAVE_TYPE_FLASHRAM;
break;
case CART_LOAD_EMU_TYPE_GAMEBOY_COLOR:
path_push(path, "emu.gbc");
save_type = FLASHCART_SAVE_TYPE_FLASHRAM;
break;
}
if (!file_exists(path_get(path))) {
path_free(path);
return CART_LOAD_ERR_EMU_NOT_FOUND;
}
menu->flashcart_error = flashcart_load_rom(path_get(path), false, progress);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_EMU;
}
path_free(path);
path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
menu->flashcart_error = flashcart_load_file(path_get(path), emulated_rom_offset);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_EMU_ROM;
}
path_ext_replace(path, "sav");
if (menu->settings.use_saves_folder) {
path_push_subdir(path, SAVES_SUBDIRECTORY);
}
menu->flashcart_error = flashcart_load_save(path_get(path), save_type);
if (menu->flashcart_error != FLASHCART_OK) {
path_free(path);
return CART_LOAD_ERR_SAVE;
}
path_free(path);
return CART_LOAD_OK;
}

38
src/menu/cart_load.h Normal file
View File

@ -0,0 +1,38 @@
/**
* @file cart_load.h
* @brief ROM/save loading functions
* @ingroup menu
*/
#ifndef CART_LOAD_H__
#define CART_LOAD_H__
#include "flashcart/flashcart.h"
#include "menu_state.h"
#include "rom_database.h"
typedef enum {
CART_LOAD_OK,
CART_LOAD_ERR_SAVES_SUBDIR,
CART_LOAD_ERR_ROM,
CART_LOAD_ERR_SAVE,
CART_LOAD_ERR_EMU_NOT_FOUND,
CART_LOAD_ERR_EMU,
CART_LOAD_ERR_EMU_ROM,
} cart_load_err_t;
typedef enum {
CART_LOAD_EMU_TYPE_NES,
CART_LOAD_EMU_TYPE_GAMEBOY,
CART_LOAD_EMU_TYPE_GAMEBOY_COLOR,
} cart_load_emu_type_t;
char *cart_load_convert_error_message (cart_load_err_t err);
cart_load_err_t cart_load_n64_rom_and_save (menu_t *menu, rom_header_t *header, flashcart_progress_callback_t progress);
cart_load_err_t cart_load_emulator (menu_t *menu, cart_load_emu_type_t emu_type, flashcart_progress_callback_t progress);
#endif

View File

@ -137,8 +137,8 @@ static struct views_s {
{ view_image_viewer_init, view_image_viewer_display }, // MENU_MODE_IMAGE_VIEWER { 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_music_player_init, view_music_player_display }, // MENU_MODE_MUSIC_PLAYER
{ view_credits_init, view_credits_display }, // MENU_MODE_CREDITS { view_credits_init, view_credits_display }, // MENU_MODE_CREDITS
{ view_load_init, view_load_display }, // MENU_MODE_LOAD { view_load_rom_init, view_load_rom_display }, // MENU_MODE_LOAD_ROM
{ view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_EMULATOR_LOAD { view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_LOAD_EMULATOR
{ view_error_init, view_error_display }, // MENU_MODE_ERROR { view_error_init, view_error_display }, // MENU_MODE_ERROR
{ view_fault_init, view_fault_display }, // MENU_MODE_FAULT { view_fault_init, view_fault_display }, // MENU_MODE_FAULT
{ NULL, NULL }, // MENU_MODE_BOOT { NULL, NULL }, // MENU_MODE_BOOT

View File

@ -28,8 +28,8 @@ typedef enum {
MENU_MODE_IMAGE_VIEWER, MENU_MODE_IMAGE_VIEWER,
MENU_MODE_MUSIC_PLAYER, MENU_MODE_MUSIC_PLAYER,
MENU_MODE_CREDITS, MENU_MODE_CREDITS,
MENU_MODE_LOAD, MENU_MODE_LOAD_ROM,
MENU_MODE_EMULATOR_LOAD, MENU_MODE_LOAD_EMULATOR,
MENU_MODE_ERROR, MENU_MODE_ERROR,
MENU_MODE_FAULT, MENU_MODE_FAULT,
MENU_MODE_BOOT, MENU_MODE_BOOT,

View File

@ -12,6 +12,7 @@ static settings_t init = {
.pal60 = false, .pal60 = false,
.show_hidden_files = false, .show_hidden_files = false,
.default_directory = "/", .default_directory = "/",
.use_saves_folder = false,
}; };
@ -25,6 +26,7 @@ void settings_load (settings_t *settings) {
settings->pal60 = mini_get_bool(ini, "menu", "pal60", init.pal60); settings->pal60 = mini_get_bool(ini, "menu", "pal60", init.pal60);
settings->show_hidden_files = mini_get_bool(ini, "menu", "show_hidden_files", init.show_hidden_files); settings->show_hidden_files = mini_get_bool(ini, "menu", "show_hidden_files", init.show_hidden_files);
settings->default_directory = strdup(mini_get_string(ini, "menu", "default_directory", init.default_directory)); settings->default_directory = strdup(mini_get_string(ini, "menu", "default_directory", init.default_directory));
settings->use_saves_folder = mini_get_bool(ini, "menu", "use_saves_folder", init.use_saves_folder);
mini_free(ini); mini_free(ini);
} }
@ -35,6 +37,7 @@ void settings_save (settings_t *settings) {
mini_set_bool(ini, "menu", "pal60", settings->pal60); mini_set_bool(ini, "menu", "pal60", settings->pal60);
mini_set_bool(ini, "menu", "show_hidden_files", settings->show_hidden_files); mini_set_bool(ini, "menu", "show_hidden_files", settings->show_hidden_files);
mini_set_string(ini, "menu", "default_directory", settings->default_directory); mini_set_string(ini, "menu", "default_directory", settings->default_directory);
mini_set_bool(ini, "menu", "use_saves_folder", settings->use_saves_folder);
mini_save(ini); mini_save(ini);

View File

@ -18,6 +18,9 @@ typedef struct {
/** @brief Default directory to navigate to when menu loads */ /** @brief Default directory to navigate to when menu loads */
char *default_directory; char *default_directory;
/** @brief Put saves into separate directory */
bool use_saves_folder;
} settings_t; } settings_t;

View File

@ -196,10 +196,10 @@ static void process (menu_t *menu) {
} }
break; break;
case ENTRY_TYPE_ROM: case ENTRY_TYPE_ROM:
menu->next_mode = MENU_MODE_LOAD; menu->next_mode = MENU_MODE_LOAD_ROM;
break; break;
case ENTRY_TYPE_EMULATOR: case ENTRY_TYPE_EMULATOR:
menu->next_mode = MENU_MODE_EMULATOR_LOAD; menu->next_mode = MENU_MODE_LOAD_EMULATOR;
break; break;
case ENTRY_TYPE_IMAGE: case ENTRY_TYPE_IMAGE:
menu->next_mode = MENU_MODE_IMAGE_VIEWER; menu->next_mode = MENU_MODE_IMAGE_VIEWER;

View File

@ -43,4 +43,5 @@ void view_error_display (menu_t *menu, surface_t *display) {
void menu_show_error (menu_t *menu, char *error_message) { void menu_show_error (menu_t *menu, char *error_message) {
menu->next_mode = MENU_MODE_ERROR; menu->next_mode = MENU_MODE_ERROR;
menu->error_message = error_message; menu->error_message = error_message;
menu->browser.valid = false;
} }

View File

@ -1,22 +1,16 @@
#include <libdragon.h> #include "../cart_load.h"
#include "boot/boot.h" #include "boot/boot.h"
#include "flashcart/flashcart.h"
#include "utils/fs.h" #include "utils/fs.h"
#include "views.h" #include "views.h"
#ifndef EMULATOR_FOLDER
#define EMULATOR_FOLDER "/emulators/"
#endif
static const char *emu_nes_rom_extensions[] = { "nes", NULL }; static const char *emu_nes_rom_extensions[] = { "nes", NULL };
static const char *emu_gameboy_rom_extensions[] = { "gb", NULL }; static const char *emu_gameboy_rom_extensions[] = { "gb", NULL };
static const char *emu_gameboy_color_rom_extensions[] = { "gbc", NULL }; static const char *emu_gameboy_color_rom_extensions[] = { "gbc", NULL };
static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL }; // static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL };
static const uint32_t eum_rom_start_address = 0x200000;
static bool load_pending; static bool load_pending;
static cart_load_emu_type_t emu_type;
static void process (menu_t *menu) { static void process (menu_t *menu) {
@ -71,86 +65,15 @@ static void draw_progress (float progress) {
} }
} }
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) { static void load (menu_t *menu) {
menu->next_mode = MENU_MODE_BOOT; cart_load_err_t err = cart_load_emulator(menu, emu_type, draw_progress);
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); if (err != CART_LOAD_OK) {
menu_show_error(menu, cart_load_convert_error_message(err));
if (file_has_extensions(path_get(path), emu_nes_rom_extensions)) { return;
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->next_mode = MENU_MODE_BOOT;
menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM;
menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH;
menu->boot_params->detect_cic_seed = true; menu->boot_params->detect_cic_seed = true;
@ -159,6 +82,22 @@ static void load (menu_t *menu) {
void view_load_emulator_init (menu_t *menu) { void view_load_emulator_init (menu_t *menu) {
load_pending = false; load_pending = false;
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
if (file_has_extensions(path_get(path), emu_nes_rom_extensions)) {
emu_type = CART_LOAD_EMU_TYPE_NES;
} else if (file_has_extensions(path_get(path), emu_gameboy_rom_extensions)) {
emu_type = CART_LOAD_EMU_TYPE_GAMEBOY;
} else if (file_has_extensions(path_get(path), emu_gameboy_color_rom_extensions)) {
emu_type = CART_LOAD_EMU_TYPE_GAMEBOY_COLOR;
// } else if (file_has_extensions(path_get(path), emu_sega_rom_extensions)) {
// emu_type = CART_LOAD_EMU_TYPE_SEGA;
} else {
menu_show_error(menu, "Unsupported ROM");
}
path_free(path);
} }
void view_load_emulator_display (menu_t *menu, surface_t *display) { void view_load_emulator_display (menu_t *menu, surface_t *display) {

View File

@ -1,6 +1,6 @@
#include "../cart_load.h"
#include "../rom_database.h" #include "../rom_database.h"
#include "boot/boot.h" #include "boot/boot.h"
#include "flashcart/flashcart.h"
#include "views.h" #include "views.h"
@ -224,50 +224,15 @@ static void draw_progress (float progress) {
} }
} }
static flashcart_save_type_t convert_save_type (db_savetype_t save_type) {
switch (save_type) {
case DB_SAVE_TYPE_EEPROM_4K:
return FLASHCART_SAVE_TYPE_EEPROM_4K;
case DB_SAVE_TYPE_EEPROM_16K:
return FLASHCART_SAVE_TYPE_EEPROM_16K;
case DB_SAVE_TYPE_SRAM:
return FLASHCART_SAVE_TYPE_SRAM;
case DB_SAVE_TYPE_SRAM_BANKED:
return FLASHCART_SAVE_TYPE_SRAM_BANKED;
case DB_SAVE_TYPE_SRAM_128K:
return FLASHCART_SAVE_TYPE_SRAM_128K;
case DB_SAVE_TYPE_FLASHRAM:
return FLASHCART_SAVE_TYPE_FLASHRAM;
default:
return FLASHCART_SAVE_TYPE_NONE;
}
}
static void load (menu_t *menu) { static void load (menu_t *menu) {
cart_load_err_t err = cart_load_n64_rom_and_save(menu, &rom_header, draw_progress);
if (err != CART_LOAD_OK) {
menu_show_error(menu, cart_load_convert_error_message(err));
return;
}
menu->next_mode = MENU_MODE_BOOT; menu->next_mode = MENU_MODE_BOOT;
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);
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
uint8_t save_type = rom_db_match_save_type(rom_header);
path_ext_replace(path, "sav");
menu->flashcart_error = flashcart_load_save(path_get(path), convert_save_type(save_type));
if (menu->flashcart_error != FLASHCART_OK) {
menu->next_mode = MENU_MODE_FAULT;
path_free(path);
return;
}
path_free(path);
menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM; menu->boot_params->device_type = BOOT_DEVICE_TYPE_ROM;
menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH; menu->boot_params->tv_type = BOOT_TV_TYPE_PASSTHROUGH;
menu->boot_params->detect_cic_seed = true; menu->boot_params->detect_cic_seed = true;
@ -278,7 +243,7 @@ static void deinit (void) {
} }
void view_load_init (menu_t *menu) { void view_load_rom_init (menu_t *menu) {
load_pending = false; load_pending = false;
path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name); path_t *path = path_clone_push(menu->browser.directory, menu->browser.entry->name);
@ -290,7 +255,7 @@ void view_load_init (menu_t *menu) {
path_free(path); path_free(path);
} }
void view_load_display (menu_t *menu, surface_t *display) { void view_load_rom_display (menu_t *menu, surface_t *display) {
process(menu); process(menu);
draw(menu, display); draw(menu, display);
@ -300,7 +265,7 @@ void view_load_display (menu_t *menu, surface_t *display) {
load(menu); load(menu);
} }
if (menu->next_mode != MENU_MODE_LOAD) { if (menu->next_mode != MENU_MODE_LOAD_ROM) {
deinit(); deinit();
} }
} }

View File

@ -38,8 +38,8 @@ void view_music_player_display (menu_t *menu, surface_t *display);
void view_credits_init (menu_t *menu); void view_credits_init (menu_t *menu);
void view_credits_display (menu_t *menu, surface_t *display); void view_credits_display (menu_t *menu, surface_t *display);
void view_load_init (menu_t *menu); void view_load_rom_init (menu_t *menu);
void view_load_display (menu_t *menu, surface_t *display); void view_load_rom_display (menu_t *menu, surface_t *display);
void view_load_emulator_init (menu_t *menu); void view_load_emulator_init (menu_t *menu);
void view_load_emulator_display (menu_t *menu, surface_t *display); void view_load_emulator_display (menu_t *menu, surface_t *display);