From 1ff9634a9b8e8cd110745d697f5d12a8d797b127 Mon Sep 17 00:00:00 2001 From: Nathaniel Walizer Date: Sun, 18 May 2025 14:14:38 -0700 Subject: [PATCH] Add SRAM load/save support --- src/cartinfo.c | 1 + src/linux/port.c | 8 ++-- src/save.c | 117 ++++++++++++++++++++++++++++------------------- src/save.h | 3 ++ 4 files changed, 79 insertions(+), 50 deletions(-) diff --git a/src/cartinfo.c b/src/cartinfo.c index 01f3b92..96e5365 100644 --- a/src/cartinfo.c +++ b/src/cartinfo.c @@ -1,6 +1,7 @@ #include "cart.h" #include "cartinfo.h" #include "port.h" +#include "save.h" void unload_cart(Cart_Info* cart) { diff --git a/src/linux/port.c b/src/linux/port.c index 17981e0..f8b4bcd 100644 --- a/src/linux/port.c +++ b/src/linux/port.c @@ -320,7 +320,6 @@ int nese_frame_ready(void* plat_data) { nese_Action action = process_events(plat->sys); switch (action) { case Action_Quit: - // TODO: Save SRAM status = -1; break; @@ -494,7 +493,9 @@ static nese_Action nese_load_cart(platform_data* plat, const char* filename) { unload_cart(&plat->cart); plat->sys->cart_header = NULL; int status = load_cart(&plat->cart, filename, plat->sys); - if (0 != status) { + if (0 == status) { + load_sram(plat->sys, filename); + } else { char message[1024]; snprintf(message, sizeof(message), "Failed to load\n%s", filename); action = modal_popup(plat, message, color_error); @@ -507,7 +508,7 @@ static nese_Action select_rom(platform_data* plat, char* file, int sz_file) { nese_Action action = Action_OK; Menu_State menu = {0}; - // TODO: Save SRAM + save_sram(plat->sys, plat->filename); while (Action_OK == action || NULL == plat->sys->cart_header) { action = run_rom_menu(plat, &menu, file, sz_file); @@ -658,6 +659,7 @@ int main(int argc, char* argv[]) { // This shall invoke menus as needed if (0 == status) { status = nese_start(&sys, &plat); + save_sram(&sys, plat.filename); } unload_cart(&plat.cart); diff --git a/src/save.c b/src/save.c index daa7ccf..7821f32 100644 --- a/src/save.c +++ b/src/save.c @@ -26,13 +26,13 @@ static int make_filename(char* filename, int max_len, const char* orig_base = basename(orig_name); const char* orig_dot = strrchr(orig_base, '.'); - int orig_path_len = orig_base - orig_name; - int orig_base_len = (NULL == orig_dot) ? strlen(orig_base) : (orig_dot - orig_base); // Part 1/4: Leading path +/* + int orig_path_len = orig_base - orig_name; if (0 == status && orig_path_len <= remain) { memcpy(filename, orig_name, orig_path_len); remain -= orig_path_len; @@ -40,6 +40,7 @@ static int make_filename(char* filename, int max_len, } else { status = -1; } +*/ // Part 2/4: Subdirectory if (0 == status && NULL != subdir) { @@ -56,7 +57,7 @@ static int make_filename(char* filename, int max_len, // Part 3/4: Basename if (0 == status && orig_base_len <= remain) { - memcpy(filename, orig_name, orig_base_len); + memcpy(filename, orig_base, orig_base_len); remain -= orig_base_len; filename += orig_base_len; } else { @@ -80,35 +81,16 @@ static int make_filename(char* filename, int max_len, } -/* System State */ - -static int make_state_filename(char* save_filename, int max_len, - const char* cart_filename) { - return make_filename( save_filename, max_len, - basename(cart_filename), - "save", "nese"); -} - -static int state_write_size(const nes* sys) { - return serialize_size(sys, nes_serdes); -} - -static int state_read(nes* sys, const void* mem, int size) { - return deserialize(sys, mem, size, nes_serdes); -} - -static int state_write(const nes* sys, void* mem, int size) { - return serialize(mem, sys, size, nes_serdes); -} +/* Generic */ -int load_state(nes* sys, const char* cart_filename) { +static int load( void* comp, const char* cart_filename, + const Serdes_Item* serdes, const char* dir, const char* ext) { int size = -1; - char state_filename[FILENAME_MAX] = {0}; - make_state_filename(state_filename, FILENAME_MAX - 1, - cart_filename); + char filename[FILENAME_MAX] = {0}; + make_filename(filename, FILENAME_MAX - 1, cart_filename, dir, ext); - FILE* file = fopen(state_filename, "rb"); + FILE* file = fopen(filename, "rb"); if (NULL != file) { fseek(file, 0L, SEEK_END); @@ -118,40 +100,31 @@ int load_state(nes* sys, const char* cart_filename) { Filemap_Mode_Read); if (NULL != mem) { - size = state_read(sys, mem, file_size); + size = deserialize(comp, mem, file_size, serdes); nese_unmap_file(mem, file_size); } fclose(file); - if (file_size == size) { - nes_Mapper* mapper = &sys->core.memory.mapper; - if (mapper->init) { - size =mapper->init(mapper, NULL, &sys->core.memory); - } else { - size = 0; - } - } else { - size = -1; - } + size = (size == file_size ? 0 : -1); } return size; } -int save_state(const nes* sys, const char* cart_filename) { +static int save( const void* comp, const char* cart_filename, + const Serdes_Item* serdes, const char* dir, const char* ext) { int size = -1; - nese_mkdir("save"); + nese_mkdir(dir); - char state_filename[FILENAME_MAX] = {0}; - make_state_filename(state_filename, FILENAME_MAX - 1, - cart_filename); + char filename[FILENAME_MAX] = {0}; + make_filename(filename, FILENAME_MAX - 1, cart_filename, dir, ext); - FILE* file = fopen(state_filename, "w+b"); + FILE* file = fopen(filename, "w+b"); if (NULL != file) { - int file_size = state_write_size(sys); + int file_size = serialize_size(comp, serdes); fseek(file, file_size - 1, SEEK_SET); fwrite("", 1, 1, file); @@ -161,7 +134,7 @@ int save_state(const nes* sys, const char* cart_filename) { Filemap_Mode_Write); if (NULL != mem) { - size = state_write(sys, mem, file_size); + size = serialize(mem, comp, file_size, serdes); nese_unmap_file(mem, file_size); } @@ -172,3 +145,53 @@ int save_state(const nes* sys, const char* cart_filename) { return size; } + + +/* System State */ + +int load_state(nes* sys, const char* cart_filename) { + int status = load(sys, cart_filename, nes_serdes, "save", "nese"); + + if (0 == status) { + nes_Mapper* mapper = &sys->core.memory.mapper; + if (mapper->init) { + status = mapper->init(mapper, NULL, &sys->core.memory); + } + } + + return status; +} + +int save_state(const nes* sys, const char* cart_filename) { + return save(sys, cart_filename, nes_serdes, "save", "nese"); +} + + +/* SRAM */ + +static const Serdes_Item sram_serdes[] = { + {"SRAM", 0, &serdes_mem, (void*)NES_SRAM_SIZE}, + {0}, +}; + +int load_sram(nes* sys, const char* cart_filename) { + int status = 0; + + if (sys->cart_header && (sys->cart_header->flags_6 & ines_Flag_Battery)) { + status = load( sys->core.memory.sram, cart_filename, + sram_serdes, "sram", "sram"); + } + + return status; +} + +int save_sram(const nes* sys, const char* cart_filename) { + int status = 0; + + if (sys->cart_header && (sys->cart_header->flags_6 & ines_Flag_Battery)) { + status = save( sys->core.memory.sram, cart_filename, + sram_serdes, "sram", "sram"); + } + + return status; +} diff --git a/src/save.h b/src/save.h index 1df9c10..594564c 100644 --- a/src/save.h +++ b/src/save.h @@ -7,5 +7,8 @@ int load_state(nes*, const char* filename); int save_state(const nes*, const char* filename); +int load_sram(nes*, const char* filename); +int save_sram(const nes*, const char* filename); + #endif // NESE_SAVE_H_