diff --git a/Makefile.common b/Makefile.common
index 5ea6f35f23..83cf8a1f55 100644
--- a/Makefile.common
+++ b/Makefile.common
@@ -128,6 +128,7 @@ OBJ += frontend/frontend.o \
tasks/tasks_internal.o \
tasks/task_content.o \
tasks/task_save_ram.o \
+ tasks/task_save_state.o \
tasks/task_file_transfer.o \
tasks/task_image.o \
libretro-common/encodings/encoding_utf.o \
diff --git a/griffin/griffin.c b/griffin/griffin.c
index 1817ee4adb..9a083112c5 100644
--- a/griffin/griffin.c
+++ b/griffin/griffin.c
@@ -814,6 +814,7 @@ DATA RUNLOOP
============================================================ */
#include "../tasks/task_content.c"
#include "../tasks/task_save_ram.c"
+#include "../tasks/task_save_state.c"
#include "../tasks/task_image.c"
#include "../tasks/task_file_transfer.c"
#ifdef HAVE_ZLIB
diff --git a/tasks/task_content.c b/tasks/task_content.c
index 89314e0f0d..7c1653b755 100644
--- a/tasks/task_content.c
+++ b/tasks/task_content.c
@@ -104,13 +104,6 @@
#define MAX_ARGS 32
-struct sram_block
-{
- unsigned type;
- void *data;
- size_t size;
-};
-
typedef struct content_stream
{
uint32_t a;
@@ -1038,179 +1031,6 @@ bool dump_to_file_desperate(const void *data,
return true;
}
-
-/**
- * save_state:
- * @path : path of saved state that shall be written to.
- *
- * Save a state from memory to disk.
- *
- * Returns: true if successful, false otherwise.
- **/
-bool content_save_state(const char *path)
-{
- retro_ctx_serialize_info_t serial_info;
- retro_ctx_size_info_t info;
- bool ret = false;
- void *data = NULL;
-
- core_serialize_size(&info);
-
- RARCH_LOG("%s: \"%s\".\n",
- msg_hash_to_str(MSG_SAVING_STATE),
- path);
-
- if (info.size == 0)
- return false;
-
- data = malloc(info.size);
-
- if (!data)
- return false;
-
- RARCH_LOG("%s: %d %s.\n",
- msg_hash_to_str(MSG_STATE_SIZE),
- (int)info.size,
- msg_hash_to_str(MSG_BYTES));
-
- serial_info.data = data;
- serial_info.size = info.size;
- ret = core_serialize(&serial_info);
-
- if (ret)
- ret = filestream_write_file(path, data, info.size);
- else
- {
- RARCH_ERR("%s \"%s\".\n",
- msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
- path);
- }
-
- free(data);
-
- return ret;
-}
-
-/**
- * content_load_state:
- * @path : path that state will be loaded from.
- *
- * Load a state from disk to memory.
- *
- * Returns: true if successful, false otherwise.
- **/
-bool content_load_state(const char *path)
-{
- unsigned i;
- ssize_t size;
- retro_ctx_serialize_info_t serial_info;
- unsigned num_blocks = 0;
- void *buf = NULL;
- struct sram_block *blocks = NULL;
- settings_t *settings = config_get_ptr();
- global_t *global = global_get_ptr();
- bool ret = filestream_read_file(path, &buf, &size);
-
- RARCH_LOG("%s: \"%s\".\n",
- msg_hash_to_str(MSG_LOADING_STATE),
- path);
-
- if (!ret || size < 0)
- goto error;
-
- RARCH_LOG("%s: %u %s.\n",
- msg_hash_to_str(MSG_STATE_SIZE),
- (unsigned)size,
- msg_hash_to_str(MSG_BYTES));
-
- if (settings->block_sram_overwrite && global->savefiles
- && global->savefiles->size)
- {
- RARCH_LOG("%s.\n",
- msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
- blocks = (struct sram_block*)
- calloc(global->savefiles->size, sizeof(*blocks));
-
- if (blocks)
- {
- num_blocks = global->savefiles->size;
- for (i = 0; i < num_blocks; i++)
- blocks[i].type = global->savefiles->elems[i].attr.i;
- }
- }
-
-
- for (i = 0; i < num_blocks; i++)
- {
- retro_ctx_memory_info_t mem_info;
-
- mem_info.id = blocks[i].type;
- core_get_memory(&mem_info);
-
- blocks[i].size = mem_info.size;
- }
-
- for (i = 0; i < num_blocks; i++)
- if (blocks[i].size)
- blocks[i].data = malloc(blocks[i].size);
-
- /* Backup current SRAM which is overwritten by unserialize. */
- for (i = 0; i < num_blocks; i++)
- {
- if (blocks[i].data)
- {
- retro_ctx_memory_info_t mem_info;
- const void *ptr = NULL;
-
- mem_info.id = blocks[i].type;
-
- core_get_memory(&mem_info);
-
- ptr = mem_info.data;
- if (ptr)
- memcpy(blocks[i].data, ptr, blocks[i].size);
- }
- }
-
- serial_info.data_const = buf;
- serial_info.size = size;
- ret = core_unserialize(&serial_info);
-
- /* Flush back. */
- for (i = 0; i < num_blocks; i++)
- {
- if (blocks[i].data)
- {
- retro_ctx_memory_info_t mem_info;
- void *ptr = NULL;
-
- mem_info.id = blocks[i].type;
-
- core_get_memory(&mem_info);
-
- ptr = mem_info.data;
- if (ptr)
- memcpy(ptr, blocks[i].data, blocks[i].size);
- }
- }
-
- for (i = 0; i < num_blocks; i++)
- free(blocks[i].data);
- free(blocks);
- free(buf);
-
- if (!ret)
- goto error;
-
- return true;
-
-error:
- RARCH_ERR("%s \"%s\".\n",
- msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE),
- path);
- return false;
-}
-
/* Load the content into memory. */
static bool load_content_into_memory(
struct retro_game_info *info,
diff --git a/tasks/task_save_state.c b/tasks/task_save_state.c
new file mode 100644
index 0000000000..f0b062771f
--- /dev/null
+++ b/tasks/task_save_state.c
@@ -0,0 +1,210 @@
+/* RetroArch - A frontend for libretro.
+ * Copyright (C) 2011-2016 - Daniel De Matteis
+ *
+ * RetroArch is free software: you can redistribute it and/or modify it under the terms
+ * of the GNU General Public License as published by the Free Software Found-
+ * ation, either version 3 of the License, or (at your option) any later version.
+ *
+ * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with RetroArch.
+ * If not, see .
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include "../core.h"
+#include "../msg_hash.h"
+#include "../verbosity.h"
+#include "tasks_internal.h"
+
+struct sram_block
+{
+ unsigned type;
+ void *data;
+ size_t size;
+};
+
+/* TODO/FIXME - turn this into actual task */
+
+/**
+ * save_state:
+ * @path : path of saved state that shall be written to.
+ *
+ * Save a state from memory to disk.
+ *
+ * Returns: true if successful, false otherwise.
+ **/
+bool content_save_state(const char *path)
+{
+ retro_ctx_serialize_info_t serial_info;
+ retro_ctx_size_info_t info;
+ bool ret = false;
+ void *data = NULL;
+
+ core_serialize_size(&info);
+
+ RARCH_LOG("%s: \"%s\".\n",
+ msg_hash_to_str(MSG_SAVING_STATE),
+ path);
+
+ if (info.size == 0)
+ return false;
+
+ data = malloc(info.size);
+
+ if (!data)
+ return false;
+
+ RARCH_LOG("%s: %d %s.\n",
+ msg_hash_to_str(MSG_STATE_SIZE),
+ (int)info.size,
+ msg_hash_to_str(MSG_BYTES));
+
+ serial_info.data = data;
+ serial_info.size = info.size;
+ ret = core_serialize(&serial_info);
+
+ if (ret)
+ ret = filestream_write_file(path, data, info.size);
+ else
+ {
+ RARCH_ERR("%s \"%s\".\n",
+ msg_hash_to_str(MSG_FAILED_TO_SAVE_STATE_TO),
+ path);
+ }
+
+ free(data);
+
+ return ret;
+}
+
+/**
+ * content_load_state:
+ * @path : path that state will be loaded from.
+ *
+ * Load a state from disk to memory.
+ *
+ * Returns: true if successful, false otherwise.
+ **/
+bool content_load_state(const char *path)
+{
+ unsigned i;
+ ssize_t size;
+ retro_ctx_serialize_info_t serial_info;
+ unsigned num_blocks = 0;
+ void *buf = NULL;
+ struct sram_block *blocks = NULL;
+ settings_t *settings = config_get_ptr();
+ global_t *global = global_get_ptr();
+ bool ret = filestream_read_file(path, &buf, &size);
+
+ RARCH_LOG("%s: \"%s\".\n",
+ msg_hash_to_str(MSG_LOADING_STATE),
+ path);
+
+ if (!ret || size < 0)
+ goto error;
+
+ RARCH_LOG("%s: %u %s.\n",
+ msg_hash_to_str(MSG_STATE_SIZE),
+ (unsigned)size,
+ msg_hash_to_str(MSG_BYTES));
+
+ if (settings->block_sram_overwrite && global->savefiles
+ && global->savefiles->size)
+ {
+ RARCH_LOG("%s.\n",
+ msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
+ blocks = (struct sram_block*)
+ calloc(global->savefiles->size, sizeof(*blocks));
+
+ if (blocks)
+ {
+ num_blocks = global->savefiles->size;
+ for (i = 0; i < num_blocks; i++)
+ blocks[i].type = global->savefiles->elems[i].attr.i;
+ }
+ }
+
+
+ for (i = 0; i < num_blocks; i++)
+ {
+ retro_ctx_memory_info_t mem_info;
+
+ mem_info.id = blocks[i].type;
+ core_get_memory(&mem_info);
+
+ blocks[i].size = mem_info.size;
+ }
+
+ for (i = 0; i < num_blocks; i++)
+ if (blocks[i].size)
+ blocks[i].data = malloc(blocks[i].size);
+
+ /* Backup current SRAM which is overwritten by unserialize. */
+ for (i = 0; i < num_blocks; i++)
+ {
+ if (blocks[i].data)
+ {
+ retro_ctx_memory_info_t mem_info;
+ const void *ptr = NULL;
+
+ mem_info.id = blocks[i].type;
+
+ core_get_memory(&mem_info);
+
+ ptr = mem_info.data;
+ if (ptr)
+ memcpy(blocks[i].data, ptr, blocks[i].size);
+ }
+ }
+
+ serial_info.data_const = buf;
+ serial_info.size = size;
+ ret = core_unserialize(&serial_info);
+
+ /* Flush back. */
+ for (i = 0; i < num_blocks; i++)
+ {
+ if (blocks[i].data)
+ {
+ retro_ctx_memory_info_t mem_info;
+ void *ptr = NULL;
+
+ mem_info.id = blocks[i].type;
+
+ core_get_memory(&mem_info);
+
+ ptr = mem_info.data;
+ if (ptr)
+ memcpy(ptr, blocks[i].data, blocks[i].size);
+ }
+ }
+
+ for (i = 0; i < num_blocks; i++)
+ free(blocks[i].data);
+ free(blocks);
+ free(buf);
+
+ if (!ret)
+ goto error;
+
+ return true;
+
+error:
+ RARCH_ERR("%s \"%s\".\n",
+ msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE),
+ path);
+ return false;
+}
diff --git a/tasks/tasks_internal.h b/tasks/tasks_internal.h
index 02606b7cc3..b819e6011e 100644
--- a/tasks/tasks_internal.h
+++ b/tasks/tasks_internal.h
@@ -145,6 +145,8 @@ bool content_save_ram_file(ram_type_t *ram);
bool content_load_ram_file(ram_type_t *ram);
bool dump_to_file_desperate(const void *data,
size_t size, unsigned type);
+bool content_save_state(const char *path);
+bool content_load_state(const char *path);
#ifdef __cplusplus
}