Rework savestate / srm saving.

This commit is contained in:
Themaister 2011-01-18 15:34:37 +01:00
parent c7e6e73bcb
commit b381350bdc
3 changed files with 105 additions and 72 deletions

130
file.c
View File

@ -23,7 +23,8 @@
#include <string.h> #include <string.h>
#include "dynamic.h" #include "dynamic.h"
ssize_t read_file(FILE* file, void** buf) // Load SNES rom only. Applies a hack for headered ROMs.
static ssize_t read_rom_file(FILE* file, void** buf)
{ {
ssize_t ret; ssize_t ret;
if (file == NULL) // stdin if (file == NULL) // stdin
@ -96,74 +97,117 @@ ssize_t read_file(FILE* file, void** buf)
return ret; return ret;
} }
void write_file(const char* path, uint8_t* data, size_t size) // Generic file loader.
static ssize_t read_file(const char *path, void **buf)
{ {
FILE *file = fopen(path, "wb"); void *rom_buf = NULL;
if ( file != NULL ) FILE *file = fopen(path, "rb");
if (!file)
{ {
SSNES_LOG("Saving state \"%s\". Size: %d bytes.\n", path, (int)size); SSNES_ERR("Couldn't open file: \"%s\"\n", path);
psnes_serialize(data, size); goto error;
if ( fwrite(data, 1, size, file) != size )
SSNES_ERR("Did not save state properly.\n");
fclose(file);
} }
fseek(file, 0, SEEK_END);
long len = ftell(file);
ssize_t rc = 0;
rewind(file);
rom_buf = malloc(len);
if (!rom_buf)
{
SSNES_ERR("Couldn't allocate memory!\n");
goto error;
}
if ((rc = fread(rom_buf, 1, len, file)) < len)
SSNES_WARN("Didn't read whole file.\n");
*buf = rom_buf;
fclose(file);
return rc;
error:
if (file)
fclose(file);
free(rom_buf);
*buf = NULL;
return -1;
} }
void load_state(const char* path, uint8_t* data, size_t size) // Dump stuff to file.
static void dump_to_file(const char *path, const void *data, size_t size)
{ {
SSNES_LOG("Loading state: \"%s\".\n", path); FILE *file = fopen(path, "wb");
FILE *file = fopen(path, "rb"); if (!file)
if ( file != NULL )
{ {
//fprintf(stderr, "SSNES: Loading state. Size: %d bytes.\n", (int)size); SSNES_ERR("Couldn't dump to file %s\n", path);
if ( fread(data, 1, size, file) != size )
SSNES_ERR("Did not load state properly.\n");
fclose(file);
psnes_unserialize(data, size);
} }
else else
{ {
SSNES_LOG("No state file found. Will create new.\n"); fwrite(data, 1, size, file);
fclose(file);
} }
} }
void load_save_file(const char* path, int type) void save_state(const char* path)
{ {
FILE *file; SSNES_LOG("Saving state: \"%s\".\n", path);
size_t size = psnes_serialize_size();
if (size == 0)
return;
file = fopen(path, "rb"); void *data = malloc(size);
if ( !file ) if (!data)
{ {
SSNES_ERR("Failed to allocate memory for save state buffer.\n");
return; return;
} }
SSNES_LOG("State size: %d bytes.\n", (int)size);
psnes_serialize(data, size);
dump_to_file(path, data, size);
free(data);
}
void load_state(const char* path)
{
SSNES_LOG("Loading state: \"%s\".\n", path);
void *buf = NULL;
ssize_t size = read_file(path, &buf);
if (size < 0)
SSNES_ERR("Failed to load state.\n");
else
{
SSNES_LOG("State size: %d bytes.\n", (int)size);
psnes_unserialize(buf, size);
}
free(buf);
}
void load_ram_file(const char* path, int type)
{
size_t size = psnes_get_memory_size(type); size_t size = psnes_get_memory_size(type);
uint8_t *data = psnes_get_memory_data(type); uint8_t *data = psnes_get_memory_data(type);
if (size == 0 || !data) if (size == 0 || !data)
{
fclose(file);
return; return;
}
int rc = fread(data, 1, size, file); void *buf = NULL;
if ( rc != size ) ssize_t rc = read_file(path, &buf);
{ if (rc <= size)
SSNES_ERR("Couldn't load save file.\n"); memcpy(data, buf, size);
}
SSNES_LOG("Loaded save file: \"%s\"\n", path); free(buf);
fclose(file);
} }
void save_file(const char* path, int type) void save_ram_file(const char* path, int type)
{ {
size_t size = psnes_get_memory_size(type); size_t size = psnes_get_memory_size(type);
uint8_t *data = psnes_get_memory_data(type); uint8_t *data = psnes_get_memory_data(type);
if ( data && size > 0 ) if ( data && size > 0 )
write_file(path, data, size); dump_to_file(path, data, size);
} }
static bool load_sgb_rom(void) static bool load_sgb_rom(void)
@ -175,7 +219,7 @@ static bool load_sgb_rom(void)
void *extra_rom_buf = NULL; void *extra_rom_buf = NULL;
ssize_t extra_rom_len = 0; ssize_t extra_rom_len = 0;
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1) if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{ {
SSNES_ERR("Could not read ROM file.\n"); SSNES_ERR("Could not read ROM file.\n");
goto error; goto error;
@ -188,7 +232,7 @@ static bool load_sgb_rom(void)
goto error; goto error;
} }
if ((extra_rom_len = read_file(extra_rom, &extra_rom_buf)) == -1) if ((extra_rom_len = read_rom_file(extra_rom, &extra_rom_buf)) == -1)
{ {
SSNES_ERR("Cannot read GameBoy rom.\n"); SSNES_ERR("Cannot read GameBoy rom.\n");
goto error; goto error;
@ -229,7 +273,7 @@ static bool load_bsx_rom(bool slotted)
void *extra_rom_buf = NULL; void *extra_rom_buf = NULL;
ssize_t extra_rom_len = 0; ssize_t extra_rom_len = 0;
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1) if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{ {
SSNES_ERR("Could not read ROM file.\n"); SSNES_ERR("Could not read ROM file.\n");
goto error; goto error;
@ -242,7 +286,7 @@ static bool load_bsx_rom(bool slotted)
goto error; goto error;
} }
if ((extra_rom_len = read_file(extra_rom, &extra_rom_buf)) == -1) if ((extra_rom_len = read_rom_file(extra_rom, &extra_rom_buf)) == -1)
{ {
SSNES_ERR("Cannot read BSX game rom.\n"); SSNES_ERR("Cannot read BSX game rom.\n");
goto error; goto error;
@ -297,7 +341,7 @@ static bool load_sufami_rom(void)
void *extra_rom_buf[2] = {NULL}; void *extra_rom_buf[2] = {NULL};
ssize_t extra_rom_len[2] = {0}; ssize_t extra_rom_len[2] = {0};
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1) if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{ {
SSNES_ERR("Could not read ROM file.\n"); SSNES_ERR("Could not read ROM file.\n");
goto error; goto error;
@ -316,7 +360,7 @@ static bool load_sufami_rom(void)
goto error; goto error;
} }
if ((extra_rom_len[i] = read_file(extra_rom[i], &extra_rom_buf[i])) == -1) if ((extra_rom_len[i] = read_rom_file(extra_rom[i], &extra_rom_buf[i])) == -1)
{ {
SSNES_ERR("Cannot read BSX game rom.\n"); SSNES_ERR("Cannot read BSX game rom.\n");
goto error; goto error;
@ -363,7 +407,7 @@ static bool load_normal_rom(void)
void *rom_buf = NULL; void *rom_buf = NULL;
ssize_t rom_len = 0; ssize_t rom_len = 0;
if ((rom_len = read_file(g_extern.rom_file, &rom_buf)) == -1) if ((rom_len = read_rom_file(g_extern.rom_file, &rom_buf)) == -1)
{ {
SSNES_ERR("Could not read ROM file.\n"); SSNES_ERR("Could not read ROM file.\n");
return false; return false;

9
file.h
View File

@ -26,12 +26,11 @@
#include <sys/types.h> #include <sys/types.h>
#include "general.h" #include "general.h"
ssize_t read_file(FILE *file, void **buf); void load_state(const char* path);
void save_state(const char* path);
void load_state(const char* path, uint8_t* data, size_t size); void load_ram_file(const char* path, int type);
void write_file(const char* path, uint8_t* data, size_t size); void save_ram_file(const char* path, int type);
void load_save_file(const char* path, int type);
void save_file(const char* path, int type);
bool init_rom_file(enum ssnes_game_type type); bool init_rom_file(enum ssnes_game_type type);

38
ssnes.c
View File

@ -489,19 +489,19 @@ static inline void load_save_files(void)
{ {
case SSNES_CART_NORMAL: case SSNES_CART_NORMAL:
case SSNES_CART_SGB: case SSNES_CART_SGB:
load_save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM); load_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
load_save_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC); load_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
break; break;
case SSNES_CART_BSX: case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED: case SSNES_CART_BSX_SLOTTED:
load_save_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM); load_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM);
load_save_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM); load_ram_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM);
break; break;
case SSNES_CART_SUFAMI: case SSNES_CART_SUFAMI:
load_save_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM); load_ram_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM);
load_save_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM); load_ram_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM);
break; break;
default: default:
@ -515,19 +515,19 @@ static inline void save_files(void)
{ {
case SSNES_CART_NORMAL: case SSNES_CART_NORMAL:
case SSNES_CART_SGB: case SSNES_CART_SGB:
save_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM); save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_CARTRIDGE_RAM);
save_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC); save_ram_file(g_extern.savefile_name_rtc, SNES_MEMORY_CARTRIDGE_RTC);
break; break;
case SSNES_CART_BSX: case SSNES_CART_BSX:
case SSNES_CART_BSX_SLOTTED: case SSNES_CART_BSX_SLOTTED:
save_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM); save_ram_file(g_extern.savefile_name_srm, SNES_MEMORY_BSX_RAM);
save_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM); save_ram_file(g_extern.savefile_name_psrm, SNES_MEMORY_BSX_PRAM);
break; break;
case SSNES_CART_SUFAMI: case SSNES_CART_SUFAMI:
save_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM); save_ram_file(g_extern.savefile_name_asrm, SNES_MEMORY_SUFAMI_TURBO_A_RAM);
save_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM); save_ram_file(g_extern.savefile_name_bsrm, SNES_MEMORY_SUFAMI_TURBO_B_RAM);
break; break;
default: default:
@ -626,14 +626,6 @@ int main(int argc, char *argv[])
init_controllers(); init_controllers();
unsigned serial_size = psnes_serialize_size();
uint8_t *serial_data = malloc(serial_size);
if (serial_data == NULL)
{
SSNES_ERR("Failed to allocate memory for states!\n");
goto error;
}
load_save_files(); load_save_files();
#ifdef HAVE_FFMPEG #ifdef HAVE_FFMPEG
@ -652,9 +644,9 @@ int main(int argc, char *argv[])
// Save or load state here. // Save or load state here.
if (driver.input->key_pressed(driver.input_data, SSNES_SAVE_STATE_KEY)) if (driver.input->key_pressed(driver.input_data, SSNES_SAVE_STATE_KEY))
write_file(g_extern.savestate_name, serial_data, serial_size); save_state(g_extern.savestate_name);
else if (driver.input->key_pressed(driver.input_data, SSNES_LOAD_STATE_KEY)) else if (driver.input->key_pressed(driver.input_data, SSNES_LOAD_STATE_KEY))
load_state(g_extern.savestate_name, serial_data, serial_size); load_state(g_extern.savestate_name);
// If we go fullscreen we drop all drivers and reinit to be safe. // If we go fullscreen we drop all drivers and reinit to be safe.
else if (driver.input->key_pressed(driver.input_data, SSNES_FULLSCREEN_TOGGLE_KEY)) else if (driver.input->key_pressed(driver.input_data, SSNES_FULLSCREEN_TOGGLE_KEY))
@ -672,13 +664,11 @@ int main(int argc, char *argv[])
deinit_recording(); deinit_recording();
#endif #endif
// Flush out SRAM (and RTC)
save_files(); save_files();
psnes_unload_cartridge(); psnes_unload_cartridge();
psnes_term(); psnes_term();
uninit_drivers(); uninit_drivers();
free(serial_data);
uninit_dlsym(); uninit_dlsym();
return 0; return 0;