chiark / gitweb /
Support for loading games in Javascript puzzles.
authorSimon Tatham <anakin@pobox.com>
Tue, 5 Sep 2017 19:48:42 +0000 (20:48 +0100)
committerSimon Tatham <anakin@pobox.com>
Tue, 5 Sep 2017 19:58:05 +0000 (20:58 +0100)
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.

emcc.c
emccpre.js
emccx.json
html/jspage.pl

diff --git a/emcc.c b/emcc.c
index 26e1ac220d171a29a0a9fa26a82a9e1de7d94729..e25fdf86dd633bc9e0d69179b0e136b52209c134 100644 (file)
--- a/emcc.c
+++ b/emcc.c
@@ -766,9 +766,9 @@ struct savefile_write_ctx {
     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;
@@ -799,6 +799,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);
+    }
+}
+
 /* ----------------------------------------------------------------------
  * Setup function called at page load time. It's called main() because
  * that's the most convenient thing in Emscripten, but it's not main()
index 16702bb129c33c54c3fe6cf01e54e271339f9564..50825556171e5442827ea93865d2ba22334a40d9 100644 (file)
@@ -299,6 +299,7 @@ function initPuzzle() {
     // '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) {
@@ -322,6 +323,31 @@ function initPuzzle() {
         }
     };
 
+    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();
+            });
+        }
+    };
+
     gametypelist = document.getElementById("gametype");
     gametypesubmenus.push(gametypelist);
 
index 25d08fecb9b48f821e62bbdf935f6709566d503c..bdab346d79b26351cf571fba4fa7616d9a976d47 100644 (file)
     '_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',
index 20e2a78f2daca6e162832a380346ddbc76c56ff7..3c3a2d6481d4ab099fb2151a63654e2675727781 100755 (executable)
@@ -210,6 +210,7 @@ ${unfinishedpara}
 ><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