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.c \
menu/actions.c \
menu/cart_load.c \
menu/components/background.c \
menu/components/boxart.c \
menu/components/common.c \
@ -47,7 +48,7 @@ SRCS = \
menu/views/file_info.c \
menu/views/image_viewer.c \
menu/views/load_emulator.c \
menu/views/load.c \
menu/views/load_rom.c \
menu/views/music_player.c \
menu/views/startup.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_music_player_init, view_music_player_display }, // MENU_MODE_MUSIC_PLAYER
{ view_credits_init, view_credits_display }, // MENU_MODE_CREDITS
{ view_load_init, view_load_display }, // MENU_MODE_LOAD
{ view_load_emulator_init, view_load_emulator_display }, // MENU_MODE_EMULATOR_LOAD
{ view_load_rom_init, view_load_rom_display }, // MENU_MODE_LOAD_ROM
{ 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 File

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

View File

@ -12,6 +12,7 @@ static settings_t init = {
.pal60 = false,
.show_hidden_files = false,
.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->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->use_saves_folder = mini_get_bool(ini, "menu", "use_saves_folder", init.use_saves_folder);
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", "show_hidden_files", settings->show_hidden_files);
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);

View File

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

View File

@ -196,10 +196,10 @@ static void process (menu_t *menu) {
}
break;
case ENTRY_TYPE_ROM:
menu->next_mode = MENU_MODE_LOAD;
menu->next_mode = MENU_MODE_LOAD_ROM;
break;
case ENTRY_TYPE_EMULATOR:
menu->next_mode = MENU_MODE_EMULATOR_LOAD;
menu->next_mode = MENU_MODE_LOAD_EMULATOR;
break;
case ENTRY_TYPE_IMAGE:
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) {
menu->next_mode = MENU_MODE_ERROR;
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 "flashcart/flashcart.h"
#include "utils/fs.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_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 };
static const uint32_t eum_rom_start_address = 0x200000;
// static const char *emu_sega_rom_extensions[] = {"smc", "gen", "smd", NULL };
static bool load_pending;
static cart_load_emu_type_t emu_type;
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) {
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 (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);
if (err != CART_LOAD_OK) {
menu_show_error(menu, cart_load_convert_error_message(err));
return;
}
path_free(path);
menu->next_mode = MENU_MODE_BOOT;
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;
@ -159,6 +82,22 @@ static void load (menu_t *menu) {
void view_load_emulator_init (menu_t *menu) {
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) {

View File

@ -1,6 +1,6 @@
#include "../cart_load.h"
#include "../rom_database.h"
#include "boot/boot.h"
#include "flashcart/flashcart.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) {
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;
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->tv_type = BOOT_TV_TYPE_PASSTHROUGH;
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;
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);
}
void view_load_display (menu_t *menu, surface_t *display) {
void view_load_rom_display (menu_t *menu, surface_t *display) {
process(menu);
draw(menu, display);
@ -300,7 +265,7 @@ void view_load_display (menu_t *menu, surface_t *display) {
load(menu);
}
if (menu->next_mode != MENU_MODE_LOAD) {
if (menu->next_mode != MENU_MODE_LOAD_ROM) {
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_display (menu_t *menu, surface_t *display);
void view_load_init (menu_t *menu);
void view_load_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_emulator_init (menu_t *menu);
void view_load_emulator_display (menu_t *menu, surface_t *display);