+/* ----------------------------------------------------------------------
+ * Called from JS to prepare a save-game file, and free one after it's
+ * been used.
+ */
+
+struct savefile_write_ctx {
+ char *buffer;
+ size_t pos;
+};
+
+static void savefile_write(void *vctx, void *buf, int len)
+{
+ struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)vctx;
+ if (ctx->buffer)
+ memcpy(ctx->buffer + ctx->pos, buf, len);
+ ctx->pos += len;
+}
+
+char *get_save_file(void)
+{
+ struct savefile_write_ctx ctx;
+ size_t size;
+
+ /* First pass, to count up the size */
+ ctx.buffer = NULL;
+ ctx.pos = 0;
+ midend_serialise(me, savefile_write, &ctx);
+ size = ctx.pos;
+
+ /* Second pass, to actually write out the data */
+ ctx.buffer = snewn(size, char);
+ ctx.pos = 0;
+ midend_serialise(me, savefile_write, &ctx);
+ assert(ctx.pos == size);
+
+ return ctx.buffer;
+}
+
+void free_save_file(char *buffer)
+{
+ sfree(buffer);
+}
+
+struct savefile_read_ctx {
+ const char *buffer;
+ int len_remaining;
+};
+
+static int savefile_read(void *vctx, void *buf, int len)
+{
+ struct savefile_read_ctx *ctx = (struct savefile_read_ctx *)vctx;
+ if (ctx->len_remaining < len)
+ return FALSE;
+ memcpy(buf, ctx->buffer, len);
+ ctx->len_remaining -= len;
+ ctx->buffer += len;
+ return TRUE;
+}
+
+void load_game(const char *buffer, int len)
+{
+ struct savefile_read_ctx ctx;
+ const char *err;
+
+ ctx.buffer = buffer;
+ ctx.len_remaining = len;
+ err = midend_deserialise(me, savefile_read, &ctx);
+
+ if (err) {
+ js_error_box(err);
+ } else {
+ select_appropriate_preset();
+ resize();
+ midend_redraw(me);
+ }
+}
+