shithub: puzzles

Download patch

ref: 721119e4a61cbb261b456dfd134811d7beb5ce98
parent: 1bf591a5735068d1853be13c5a4255962835d5fe
author: Simon Tatham <anakin@pobox.com>
date: Tue Sep 5 16:48:42 EDT 2017

Support for loading games in Javascript puzzles.

This is done by showing a dialog containing an <input type="file">
through which the user can 'upload' a save file - though, of course,
the 'upload' doesn't go to any HTTP server, but only into the mind of
the Javascript running in the same browser.

It would be even nicer to support drag-and-drop as an alternative UI
for getting the save file into the browser, but that isn't critical to
getting the first version of this feature out of the door.

--- a/emcc.c
+++ b/emcc.c
@@ -766,9 +766,9 @@
     size_t pos;
 };
 
-static void savefile_write(void *wctx, void *buf, int len)
+static void savefile_write(void *vctx, void *buf, int len)
 {
-    struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)wctx;
+    struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)vctx;
     if (ctx->buffer)
         memcpy(ctx->buffer + ctx->pos, buf, len);
     ctx->pos += len;
@@ -797,6 +797,40 @@
 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);
+    }
 }
 
 /* ----------------------------------------------------------------------
--- a/emccpre.js
+++ b/emccpre.js
@@ -299,6 +299,7 @@
     // 'number' is used for C pointers
     get_save_file = Module.cwrap('get_save_file', 'number', []);
     free_save_file = Module.cwrap('free_save_file', 'void', ['number']);
+    load_game = Module.cwrap('load_game', 'void', ['string', 'number']);
 
     document.getElementById("save").onclick = function(event) {
         if (dlg_dimmer === null) {
@@ -317,6 +318,31 @@
             dlg_form.appendChild(document.createTextNode("."));
             dlg_form.appendChild(document.createElement("br"));
             dialog_launch(function(event) {
+                dialog_cleanup();
+            });
+        }
+    };
+
+    document.getElementById("load").onclick = function(event) {
+        if (dlg_dimmer === null) {
+            dialog_init("Upload saved-game file");
+            var input = document.createElement("input");
+            input.type = "file";
+            input.multiple = false;
+            dlg_form.appendChild(input);
+            dlg_form.appendChild(document.createElement("br"));
+            dialog_launch(function(event) {
+                if (input.files.length == 1) {
+                    var file = input.files.item(0);
+                    var reader = new FileReader();
+                    reader.addEventListener("loadend", function() {
+                        var string = reader.result;
+                        load_game(string, string.length);
+                    });
+                    reader.readAsBinaryString(file);
+                }
+                dialog_cleanup();
+            }, function(event) {
                 dialog_cleanup();
             });
         }
--- a/emccx.json
+++ b/emccx.json
@@ -18,9 +18,10 @@
     '_timer_callback',
     // Callback from button presses in the UI outside the canvas
     '_command',
-    // Game-saving functions
+    // Game-saving and game-loading functions
     '_get_save_file',
     '_free_save_file',
+    '_load_game',
     // Callbacks to return values from dialog boxes
     '_dlg_return_sval',
     '_dlg_return_ival',
--- a/html/jspage.pl
+++ b/html/jspage.pl
@@ -210,6 +210,7 @@
 ><li id="specific">Enter game ID</li
 ><li id="random">Enter random seed</li
 ><li id="save">Download save file</li
+><li id="load">Upload save file</li
 ></ul></li
 ><li>Type...<ul id="gametype"></ul></li
 ><li class="separator"></li